需要具备的基础TCP协议的四次挥手

【目的】 验证FIN_WAIT_2的超时时间

【环境】Ubuntu 20.04 LTS
【工具】python, wireshark
【命令】ss,nc

首先通过python写一个服务端代码
FIN_WAIT_2的超时时间
开始接收客户端连接

然后通过nc命令连接服务端
FIN_WAIT_2的超时时间

通过wireshark观察到三次握手过程

FIN_WAIT_2的超时时间
通过ss命令也能查看到连接情况
FIN_WAIT_2的超时时间
这个时候通过nc给服务端发送个字符串(if you like it)数据
FIN_WAIT_2的超时时间
通过wireshark也能看到发送的数据

FIN_WAIT_2的超时时间

我们再通过服务端接收客户端发送的数据
FIN_WAIT_2的超时时间

以上都是正常的逻辑。

接下来在客户端通过CTRL+C断开连接,即客户端主动断开连接.
FIN_WAIT_2的超时时间
通过wireshark也能观察到
FIN_WAIT_2的超时时间
客户端发送了FIN, 服务端返回了ACK, 客户端进入到FIN_WAIT_2的状态,服务端进入到CLOSE_WAIT状态

通过ss命令也能看到对应的状态
FIN_WAIT_2的超时时间

但是过了一小会你再执行ss命令时,你会发现FIN_WAIT_2的状态没有了.
FIN_WAIT_2的超时时间
服务端都没有发送FIN, 也没有看到客户端的TIME_WAIT状态. 客户端直接进入到了CLOSED

【原因】
主动关闭连接的一方在进入到FIN_WAIT_2状态之后,在n秒的时间内没有收到对端的FIN包,则主动关闭一方会强制将socket关闭,状态直接进入到CLOSED

查看FIN_WAIT_2的默认超时时间
FIN_WAIT_2的超时时间

细心的读者可能会注意到, 服务端会进入到CLOSE_WAIT状态. 再仔细看的话

FIN_WAIT_2的超时时间
Recv-Q队列里面有一个字节的数据没有读取.
那么我们读取这个字节看一下是什么
FIN_WAIT_2的超时时间
读取到的是空字节,这个空字节产生的原因是之前客户端通过CTRL+C断开连接的时候,服务端内核向服务端程序’追加’的一个空字节,表示客户端断开了连接.服务端程序根据读取到的是空字节,就可以知道对端断开了连接.于是服务端也需要断开连接.

FIN_WAIT_2的超时时间
再执行ss命令查看
FIN_WAIT_2的超时时间
发现之前的CLOSE_WAIT也没有了,正常关闭了.

但是呢,通过wireshark观察

FIN_WAIT_2的超时时间
服务端调用close方法后,服务端向客户端发送了FIN,但是客户端已经在FIN_WAIT_2超时时间之后已经关闭了连接,状态已经是CLOSED了.服务端这个时候向一个已经不存在的连接发送FIN,于是客户端向服务端响应了一个RST包.

关于RST的相关知识,可以阅读我的另一篇文章

    个人网站
FIN_WAIT_2的超时时间

相关文章: