socket编程有两个典型的接收发送方式:轮询方式和select侦听及管道中断方式。
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。而我们所说的socket编程指的是利用soket接口来实现自己的业务和协议。
综上所述:Socke接口属于软件抽象层,而sokcket编程却是标准的应用层开发。
OSI 七层模型通过七个层次化的结构模型(物理层,数据链路层,网络层,传输层,会话层,表示层,应用层)使不同的系统不同的网络之间实现可靠的通讯,因此其最主要的功能就是帮助不同类型的主机实现数据传输 。完成中继功能的节点通常称为中继系统。一个设备工作在哪一层,关键看它工作时利用哪一层的数据头部信息。网桥工作时,是以MAC头部来决定转发端口的,因此显然它是数据链路层的设备。
表示层(Presentation Layer)是OSI模型的第六层,它对来自应用层的命令和数据进行解释,对各种语法赋予相应的含义,并按照一定的格式传送给会话层。其主要功能是“处理用户信息的表示问题,如编码、数据格式转换和加密解密”等。
可以看到Socke接口处于OSI 七层模型的表示层。利用socket接口编程的代码处于应用层。
应用层(Application Layer)是OSI参考模型的最高层,它是计算机用户,以及各种应用程序和网络之间的接口,其功能是直接向用户提供服务,完成用户希望在网络上完成的各种工作。它在其他6层工作的基础上,负责完成网络中应用程序与网络操作系统之间的联系,建立与结束使用者之间的联系,并完成网络用户提出的各种网络服务及 应用所需的监督、管理和服务等各种协议。此外,该层还负责协调各个应用程序间的工作。
TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于端到端的通讯。
可以看到无论七层协议和四层协议的socket编程和TCP的三次握手都没有毛关系,都被 socket的接口函数connect一人搞定了,咱们只需要调用接口就可以了。哪些面试时经常问socket的三次握手协议是什么人都是外行。作为一个非底层的应用层开发人员,你对它知道的再清楚也没有用,只能考察面试人员的记忆能力而已。不用过于关注这些零碎的事,只要有印象就可以了,知道有这个事情就可以,具体问度娘。当然完全不知道也不好,有很多新技术并不是很难,而是最可怕的是根本一点不知道。若你有所了解,在开发时才向那方面想。所以软件开发重在接触的知识面,实际开发过项目,不是比谁记得准确。说实话我开发socket好几年,你让我背诵TCP的三次握手我也紧张,答不全。
socket编程有两个典型的接收发送方式:
1..轮询方式。阻塞方式创建socket,快速轮询方式接收消息,不判断是否可写(不考虑网卡满的极端情况)直接发送消息。套接字工作流程结构图如下:
2.select侦听及管道中断方式。非阻塞方式建立socket,把本地管道文件描述符和socket可读文件描述符加入fd_set,用select函数侦听消息。当需要立即发送消息,通过本地管道写文件描述符写入消息。当服务器端发送过来消息或接收到本地管道消息,select立即结束等待并且返回是超时还是收到消息或socket异常。根据用函数FD_ISSET判断fd_set是管道消息还是socket消息。该种方式可以达到零延迟的效果,速度远比快速轮询方式省电和及时。第三方socket库基本都是使用的是快速轮询方式。可以看到自己写socket开发的优势很明显。
注意:等需要长期通过select侦听消息时,不能把可写文件描述符加入fd_set由select函数监控。因为只要网卡不满,可写文件描述符号都处于可写状态,select立即结束等待,打不到等待消息的效果,当然你想发送消息时想判断网卡是否满了,就可以通过把可写文件描述符加入fd_set由select函数结合FD_ISSET来判断出来是否可写。
一般socket编程写出来都是一个死循环线程或进程,就是有始无终的线程或进程。所以大家也不用纠结为何服务端没有终止符号。客户端有终止符号也是在外部重新起了一个一样socket线程,让原来socket安乐死。在linux中尽量别强杀进程,不然很容易出现脏数据,尽量让它在完成所有工作进入退出入口后自然的死亡。