理解了这些异常现象才敢说真正懂了TCP协议
我们先试着理解第一点,accept会通过软中断陷入内核中,最终会调用tcp协议的inet_csk_accept函数,该函数会从队列中查找是否有处于ESTABLISHED状态的套接字。如果有则返回该套接字,否则阻塞当前进程。也就是说这里只是一个查询的过程,并不参与三次握手的任何逻辑。 三次握手的本质是什么呢?实际上就是客户端与服务端一个不断交流的过程,而这个交流过程就是通过3个数据包完成的。而这个数据包的发送和处理实际上都是在内核中完成的。对于TCP的服务端来说,当它收到SYNC数据包时,就会创建一个套接字的数据结构并给客户端回复ACK,再次收到客户端的ACK时会将套接字数据结构的状态转换为ESTABLISHED,并将其发送就绪队列中。而这整个过程跟应用程序没有半毛钱的关系。 当上面套接字加入就绪队列时,accept函数就被唤醒了,然后就可以获得新的套接字并返回。但我们回过头来看一下,在accept返回之前,其实三次握手已经完成,也就是连接已经建立了。 另外一个是如果accept没有返回,客户端是否可以发送数据?答案是可以的。因为数据的发送和接受都是在内核态进行的。客户端发送数据后,服务端的网卡会先接收,然后通过中断通知IP层,再上传到TCP层。TCP层根据目的端口和地址将数据存入关联的缓冲区。如果此时应用程序有读操作(例如read或recv),那么数据会从内核态的缓冲区拷贝到用户态的缓存。否则,数据会一直在内核态的缓冲区中。总的来说,TCP的客户端是否可以发送数据与服务端程序是否工作没有任何关系。 当然,如果是整个机器都卡死了,那就是另外一种情况了。这种情况就我们之前分析的第2种情况一直了。因为,由于机器完全卡死,TCP服务端无法接受任何消息,自然也无法给客户端发送任何应答报文。 总结 今天我们主要介绍了连接建立过程中的各种异常情况,还有另外一种情况是在数据的传输过程中。比如传输过程中服务器突然掉电,或者程序crash等,后续我们将详细这些异常情况下在协议层的表现。
(编辑:源码门户网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |