加入收藏 | 设为首页 | 会员中心 | 我要投稿 南京站长网 (https://www.025zz.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 运营中心 > 网站设计 > 教程 > 正文

网络编程-再看TCP的四次挥手

发布时间:2019-07-16 16:51:45 所属栏目:教程 来源:守望先生
导读:副标题#e# 前言 四次挥手 四次挥手的流程在很多地方都可以看到,这里简略介绍一下,其最常见流程如下图所示: 其大体流程如下: 客户端发其结束请求,发送seq=X,处于FIN_WAIT_1状态 服务端收到结束请求,发送应答ACK=X+1,处于CLOSE_WAIT状态 客户端收到X

假设一开始已经有一个连接在1234端口建立,我们关闭这个连接;过一会我们在同样的ip和端口建立连接,但是TCP必须防止在前一次连接中的老的报文在它原先的连接已终止后,还出现在这个新的连接中,因此,TCP将不允许在处于TIME_WAIT状态的ip和端口处建立新的连接。而2MSL时间过后,老的报文早已在网络中消失了,也就避免了这种情况的发生。

这种情况可以很容易通过《网络编程-一个简单的echo程序》的server程序来观察:

  1. $ ./server  #在一个终端启动server, 
  2. $ ./client 127.0.0.1 1234 #在另一个终端启动client 

在服务端终端ctrl+c终止服务端,然后再次启动server:

  1. $ ./server 
  2. bind error: Address already in use 
  3. $ netstat -anop|grep :1234 
  4. tcp        1      0 127.0.0.1:33722         127.0.0.1:1234          CLOSE_WAIT  11691/client     off (0.00/0/0) 
  5. tcp        0      0 127.0.0.1:1234          127.0.0.1:33722         FIN_WAIT2   -                timewait (57.92/0/0) 

终止服务端后,服务端处于TIME_WAIT状态,此时再次启动server,将不能使用原来的ip和端口建立连接,因此出现Address already in use的报错。

但是需要注意:

  • 由于客户端通常使用的是临时端口(仔细观察会发现,客户端每次启动使用的端口基本都不一样),因此客户端即便处于TIME_WAIT状态,也不影响它马上再次启动
  • 一些实现允许一个新的连接请求仍然处于TIME_WAIT状态的连接,只要新的seq大于该连接的前一个连接的最后序号
  • 通过设置选项SO_REUSEADDR,可以让一个进程重新使用仍处于TIME_WAIT状态的socket

半打开的TCP连接

假设一个连接建立之后,突然有一方异常终止连接了,但是另一个不知道,这个时候TCP的连接就是半打开的。如果服务端不加处理,那么最终就会导致服务端有大量的半打开连接。那么服务端如何知道客户端的连接已经异常终止了呢?如果等待服务端发送数据出错时发现,那么这个时候可能已经太晚了。

幸运的是,TCP有保活定时器。即服务端可以通过设置保活选项来了解客户端是否已经终止连接。

通过下面的方式可以看到很多连接有这样的定时器:

  1. $ netstat -npo|grep keepalive 
  2. tcp        0      0 192.168.0.103:50832     59.111.179.136:443      ESTABLISHED 5882/chrome      keepalive (37.33/0/0) 
  3. tcp        0      0 192.168.0.103:50638     154.8.131.191:443       ESTABLISHED 5882/chrome      keepalive (0.00/0/0) 
  4. tcp        0      0 192.168.0.103:59330     203.107.41.32:9026      ESTABLISHED 5882/chrome      keepalive (0.35/0/0) 
  5. tcp        0      0 127.0.0.1:45632         127.0.0.1:1080          ESTABLISHED 5886/firefox     keepalive (335.28/0/0) 
  6. tcp        0      0 192.168.0.103:49940     59.56.78.189:443        ESTABLISHED 5882/chrome      keepalive (26.36/0/0) 

但可惜的是,这样的定时器时间太长了,并且它不能代表应用程序能够正常工作,能够正常收发数据,因此应用层常常也会实现一个心跳机制。

总结

本文花了大量篇幅介绍了TIME_WAIT状态,这也是面试中常问的问题,重新梳理TCP的四次挥手是很有必要的。

(编辑:南京站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读