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

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

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

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

前言

四次挥手

四次挥手的流程在很多地方都可以看到,这里简略介绍一下,其最常见流程如下图所示:

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

其大体流程如下:

  • 客户端发其结束请求,发送seq=X,处于FIN_WAIT_1状态
  • 服务端收到结束请求,发送应答ACK=X+1,处于CLOSE_WAIT状态
  • 客户端收到X的应答后,处于FIN_WAIT_2状态,此时还可以接收来自服务端的数据
  • 服务端没有数据要发送,也发送结束请求,seq=Y,处于LAST_ACK状态
  • 客户端又收到服务端的结束请求,客户端回应ACK,此时处于TIME_WAIT状态,确保ACK能够到达服务端;服务端收到客户端最终ACK,关闭连接。
  • 2MSL时间结束后,无论服务端是否收到最终ACK,客户端完全结束连接

作为一种最常见的四次挥手场景,我们可能习以为常了,但需要注意的是,连接的断开并不只有这种情况,还可以是服务端发起主动关闭,或者双方同时发起,但这不是本文关注的重点。我们直接看看四次挥手有哪些需要注意的。

什么是TCP的半关闭

TCP半关闭指的是一端结束发送后还能够接受来自另一端的数据。也就是说,虽然客户端准备断开连接并且发送了FIN报文,客户端还是可以接收来自服务端的数据。不过这种关闭方式不能使用close接口,而需要使用shutdown:

  1. #include <sys/socket.h> 
  2. int shutdown(int sockfd, int how); 

并且how参数值为SHUT_WR,即1,表明shutdown for writing ,仅关闭本端的发送。

为什么要四次挥手

为什么建立一个TCP连接需要三次握手,而终止一个连接需要四次挥手呢?这是因为TCP半关闭造成的。由于一个TCP连接是全双工的,在两个方向上都能传输数据,因此两个方向就需要单独关闭。所以这个流程是这样的:

  • 客户端执行主动关闭,发送FIN报文,告诉服务端,我没有数据要发送了,我要关闭连接,当然了,你有啥数据要给我,我随时候着
  • 服务端收到后,必须及时告诉客户端我收到了,因此先回复客户端一个ACK。但是服务端可能还有未发送完的数据,因此它可以将自己未完成的数据进行发送,发送完成之后,再发送给客户端FIN报文,表明我也没啥要发送的了,关闭吧
  • 客户端收到后,也回复ACK响应,最终关闭连接

因而整个过程需要四次挥手。

为什么要TIME_WAIT状态

TIME_WAIT也称为2MSL等待时间。MSL为报文最大生存时间,它是任何报文在被丢弃前存在于网络内的最长时间。这个时间在不同类型的系统中可能有所不同,但这不是关键。在我个人的机器上,可以借助netstat命令和nc命令通过下面的方式观察到。在终端1监听1234端口:

  1. $ nc -l 1234 

在终端2连接到1234端口:

  1. $ nc 127.0.0.1 1234 

在终端3通过netstat命令观察:

  1. $ netstat -anpoc|grep :1234 

然后在终端1按ctrl+c,终止连接,立刻观察终端3的结果,我们发现:

  1. tcp        0      0 127.0.0.1:1234          127.0.0.1:33524         TIME_WAIT   -                timewait (59.76/0/0) 
  2. tcp        0      0 127.0.0.1:1234          127.0.0.1:33524         TIME_WAIT   -                timewait (58.74/0/0) 
  3. tcp        0      0 127.0.0.1:1234          127.0.0.1:33524         TIME_WAIT   -                timewait (57.71/0/0) 
  4. tcp        0      0 127.0.0.1:1234          127.0.0.1:33524         TIME_WAIT   -                timewait (56.69/0/0) 

我们可以观察到,服务端当前处于TIME_WAIT,且有一个timewait的定时器,为1分钟。

netstat命令和nc命令的使用可以分别参考《不可不知的网络命令-netstat》和《网络工具中的”瑞士军刀“-nc》。

TIME_WAIT状态的存在主要考虑以下两个方面:

  • 实现可靠的四次挥手
  • 避免收到老的报文

(编辑:核心网)

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

热点阅读