linux内核TCP四次挥手过程分析

根据前一篇介绍TCP三次握手内核代码分析,下面来大致分析一下,四次挥手过程。

首先上一张四次挥手图片:
linux内核TCP四次挥手过程分析由上图可以观察到是客户端先发起的close操作(服务器先发起close操作也是同样的流程)。
(1)谁先close套接字,谁就先发一个fin=1的数据包到对端(同时会把自己socket状态改成TCP_FIN_WAIT1),对端收到数据包之后,会判断是否含有fin=1的标志,如果有的话,则把当前socket的状态改为TCP_CLOSE_WAIT(也就是上图中的server端CLOSE_WAIT)
(2)server端由于是TCP_ESTABLISHED状态(ESTABLISHED),所以无论接收到对端socket发过来的任何数据都会回复一个相应的ACK(对应于上图中ACK=1,seq=v,ack=u+1),紧接着如果server端不再向这个socket发送数据的时候,他也会发送一个fin=1的包,并且此时会带上ACK=1,表示我是为了回复上一次你给我的FIN=1那个数据包(意思就是你给我fin=1代表你不想发数据给我了,我这边如果不想发数据给你的话,也会发送fin=1的数据包),同时把socket状态改为TCP_LAST_ACK
(3)client收到fin=1数据包的ACK之后,知道了服务器已经知晓我不给他发送数据了,此时会关闭socket的发送功能,然后把socket的状态改成TCP_FIN_WAIT2,同时开启定时器(定时时间为2MSL,定时器的作用是等待时间内是否会接收到server端的FIN数据包,如果不再收到说明服务器收到了我后续的ACK数据包,ACK代表客户端也知道服务器不再发送数据给我了),然后在发送一个ACK告知服务器我已知晓FIN=1(即你也不发送数据给我了)
(4)服务器收到客户端的ACK之后,就知道客户端已知晓我不再给客户端发送数据了,此时针对于这个客户端socket收发功能都已没有,所以会直接清除这个socket配置
(5)客户端定时器时间之内没有再次接收到FIN则认为服务器已收到ACK,此时关闭socket连接



上层应用close-----》socket_file_ops->release(也就是sock_close)-----》sock_release-----sock->ops->release(也就是socket创建时inet_stream_ops->release,inet_release)-------》sk->sk_prot->close(也就是tcp_prot->close,tcp_close)------》tcp_send_fin到这里发送fin=1的数据包,更改状态为TCP_FIN_WAIT1

net/ipv4/tcp_input.c:之后,服务器接收函数tcp_rcv_state_process-----》tcp_data_queue-------》tcp_fin到这里服务器收到fin数据包,更改状态为TCP_CLOSE_WAIT,同时会发送FIN=1的数据包,调用tcp_send_fin,发送ACK,调用tcp_ack_snd_check

net/ipv4/tcp_input.c:客户端收到服务器第一次ACK会把状态改成TCP_FIN_WAIT2,并同时开启定时器来接收FIN数据包tcp_time_wait(sk, TCP_FIN_WAIT2, tmo),然后发送ACK,tcp_send_ack(sk);

服务器收到ACK,调用tcp_done,销毁socket
客户端定时器超时,调用tcp_done,销毁socket