需要具备的基础TCP协议的四次挥手
【目的】 验证FIN_WAIT_2的超时时间
【环境】Ubuntu 20.04 LTS
【工具】python, wireshark
【命令】ss,nc
首先通过python写一个服务端代码
开始接收客户端连接
然后通过nc命令连接服务端
通过wireshark观察到三次握手过程
通过ss命令也能查看到连接情况
这个时候通过nc给服务端发送个字符串(if you like it)数据
通过wireshark也能看到发送的数据
我们再通过服务端接收客户端发送的数据
以上都是正常的逻辑。
接下来在客户端通过CTRL+C断开连接,即客户端主动断开连接.
通过wireshark也能观察到
客户端发送了FIN, 服务端返回了ACK, 客户端进入到FIN_WAIT_2的状态,服务端进入到CLOSE_WAIT状态
通过ss命令也能看到对应的状态
但是过了一小会你再执行ss命令时,你会发现FIN_WAIT_2的状态没有了.
服务端都没有发送FIN, 也没有看到客户端的TIME_WAIT状态. 客户端直接进入到了CLOSED
【原因】
主动关闭连接的一方在进入到FIN_WAIT_2状态之后,在n秒的时间内没有收到对端的FIN包,则主动关闭一方会强制将socket关闭,状态直接进入到CLOSED
查看FIN_WAIT_2的默认超时时间
细心的读者可能会注意到, 服务端会进入到CLOSE_WAIT状态. 再仔细看的话
Recv-Q队列里面有一个字节的数据没有读取.
那么我们读取这个字节看一下是什么
读取到的是空字节,这个空字节产生的原因是之前客户端通过CTRL+C断开连接的时候,服务端内核向服务端程序’追加’的一个空字节,表示客户端断开了连接.服务端程序根据读取到的是空字节,就可以知道对端断开了连接.于是服务端也需要断开连接.
再执行ss命令查看
发现之前的CLOSE_WAIT也没有了,正常关闭了.
但是呢,通过wireshark观察
服务端调用close方法后,服务端向客户端发送了FIN,但是客户端已经在FIN_WAIT_2超时时间之后已经关闭了连接,状态已经是CLOSED了.服务端这个时候向一个已经不存在的连接发送FIN,于是客户端向服务端响应了一个RST包.
关于RST的相关知识,可以阅读我的另一篇文章