在计算机网络中,TCP/IP保证了数据的可靠性传输,但是该可靠性传输时建立在链路可用的情况下的,也就是说在链路可用的情况下,该协议可用保证数据可靠的传输到对端。
socket就是在TCP/IP协议(当然还包含其他协议)之上的更高层次的系统API,socket底层使用了TCP/IP来保证了链路在可用的情况下,数据可靠的传输到对端,那么应用层在使用socket的时候读写数据的时候就一定能保证数据可靠的传输了吗?答案是:否,为什么会这样?下面将通过分析socket的实现机制来进行相应的说明。
我们通过对linux系统中的socket的数据流传输机制的分析来说明为什么直接使用socket机制来传输数据是不可靠的。socket的使用相信大家都不会陌生,服务端监听端口,客户端指定端口连接到服务器端,然后就可以进行数据的传输了,但是却很少关系我们在调用socket的send方法之后,我们的数据是怎么样被发送到对端的?
在了解数据传输之前,需要去了解一下linux的用户态和内核态的概念。
socket在调用send方法之后,用户空间的数据会被拷贝到内核空间的socket的缓冲区(可以同socket的OPTION设置)(如果使用DMA可以减少该过程)(内核缓冲区是内核为socket分配的内存,用于缓存需要发送的数据),而且可以通过设置TCP_NODLAY来设置是否即时发送内核缓冲区的数据到对端(默认是关闭的,至于为什么关闭这个网上有很多文章说明,最主要是提高数据有效载荷)。如果在使用socket进行数据传输的时候没有设置该选项,那么就会出现一个问题,应用层多个业务多次send之后,那几次调用发送的数据可能仅