美文网首页
使用TCP/IP传输电信号:断开连接(4次挥手)并删除套接字

使用TCP/IP传输电信号:断开连接(4次挥手)并删除套接字

作者: robot_test_boy | 来源:发表于2022-07-04 00:43 被阅读0次

    数据传输完成,协议栈在设计上允许任何一方先发起断开过程。

    以服务器一方发起断开过程为例。

    首先,服务器一方的应用程序会调用Socket库的close程序。然后,服务器的协议栈会生成包含断开信息的TCP头部,将控制位中的FIN比特设为1。接下来,协议栈会委托IP模块向客户端发送数据。同时,服务器的套接字中也会记录下断开操作的相关信息。

    四次挥手

    当客户端收到服务器发来的FIN为1的TCP头部时,客户端的协议栈会将自己的套接字标记为进入断开操作状态。然后,为了告知服务器已收到FIN为1的包,客户端会向服务器返回一个ACK号。这些操作完成后,协议栈就可以等待应用程序来取数据了。应用程序就会调用read来读取数据。这时,协议栈不会向应用程序传递数据,而是会告知应用程序(浏览器)来自服务器的数据已经全部收到了。

    客户端应用程序会调用close来结束数据收发操作,这时客户端的协议栈也会和服务器一样,生成一个FIN比特为1的TCP包,然后委托IP模块发送给服务器。一段时间之后,服务器就会返回ACK号。到这里,客户端和服务器的通信就全部结束了。


    和服务器的通信结束之后,用来通信的套接字就可以删除了。不过,套接字并不会立即被删除,而是会等待一段时间之后再被删除。

    客户端先发起断开,则断开的顺序如下:

    1)客户端发送FIN

    2)服务器返回ACK号

    3)服务器发送FIN

    4)客户端返回ACK号

    如果最后客户端返回的ACK号丢失了,结果会如何呢?这时,服务器没有接收到ACK号,可能会重发一次FIN。

    如果这时客户端的套接字已经删除了,会发生什么事呢?套接字被删除,那么套接字中保存的控制信息也就跟着消失了,套接字对应的端口号就会被释放出来。

    这时,如果别的应用程序要创建套接字,新套接字碰巧又被分配了同一个端口号,而服务器重发的FIN正好到达,会怎么样呢?本来这个FIN是要发给刚刚删除的那个套接字的,但新套接字具有相同的端口号,于是这个FIN就会错误地跑到新套接字里面,新套接字就开始执行断开操作了。之所以不马上删除套接字,就是为了防止这样的误操作。

    至于具体等待多长时间,这和包重传的操作方式有关。网络包丢失之后会进行重传,这个操作通常要持续几分钟。

    如果重传了几分钟之后依然无效,则停止重传。在这段时间内,网络中可能存在重传的包,也就有可能发生前面讲到的这种误操作,因此需要等待到重传完全结束。协议中对于这个等待时间没有明确的规定,一般来说会等待几分钟之后再删除套接字。

    本文摘取自周自恒翻译的户根勤编写的《网络是怎样连接的》

    相关文章

      网友评论

          本文标题:使用TCP/IP传输电信号:断开连接(4次挥手)并删除套接字

          本文链接:https://www.haomeiwen.com/subject/zpthbrtx.html