linux内核协议栈之TCP四次挥手

linux内核协议栈之TCP四次挥手

Posted by lwk on January 12, 2020

上一篇剖析了TCP三次握手过程,这次看下TCP四次挥手过程,相关内核代码和TCP三次握手有重复地方,所以会粗略截图。

先看下tcp四次挥手抓包情况: image

从抓包可以看出:

172...9首先向172...10发送FIN+ACK包(以下简称9和10)

1、9给10回一个FIN+ACK报文

2、10给9回一个ACK报文

3、10给9又回一个FIN+ACK报文

4、9给10回一个ACK报文

9首先调用close,通过系统调用

image

接着调用__close_fd,获取访问锁,释放文件描述符,释放访问锁,然后调用flip_close

image

__put_ununsed_fd功能主要是根据待回收的fd确定下一个待分配的fd image

image

接下来看下fput的调用 image

image

image

image

image

image

接下来看下sock_close的定义 image

image

其中sock->ops->release最终调用的是net/ipv4/af_inet.cd的 inet_release

image image

image

image

调用tcp_send_fin之后,紧接着就进入了TCP四次挥手的第一次挥手阶段:

image

以上是第一次挥手过程,即9向10发送fin包。

接下来是第二次挥手:

接着等待另一方回应,从上一篇三次握手可以知道,处理TCP不同状态码的函数为net/ipv4/tcp_input.c中的tcp_rcv_state_process,现在主要是等待对方对fin的ack,让套接字进入fin_wait2状态

image

这时,10收到fin报文,同样是tcp_rcv_state_process处理,根据状态(现在是连接建立ESTABLISHED)调用tcp_data_queue进入close_wait状态

image 该函数将套接字状态切换为close_wait,即10状态为close_wait,然后等待新数据发送ack

image

第三次挥手:

10也调用close,状态由close_wait变为last_ack image

第四次挥手:

9收到fin报文后,回复ack,并进入time_wait image 10收到ack后,进入closed状态,回收资源

image 至此,TCP四次挥手完成。

总结一下: image