TCP连接的关闭过程

本文讲述关于TCP连接关闭的系统状态、系统调用、报文。

客户端一般是主动关闭方,直接在程序在调用close()函数发出关闭请求(发送Fin报文)。

服务器端一般是关闭被动方,不会主动调用close()函数。

TCP连接关闭阶段的状态

当TCP其中一方调用close()函数之后,TCP连接进入四次挥手阶段。

FIN_WAIT_1
连接中断主动方的状态。
调用close()函数,发出连接中断请求FIN报文后进入该状态,等待对方的响应。

FIN_WAIT_2
连接中断主动方的状态。
收到了对方的中断请求ACK报文后进入该状态,等待对方的FIN报文。

TIME_WAIT
连接中断主动方的状态。
收到了对方的FIN报文,进入该状态,并发回最后一个ACK报文。然后等待一段时间(2倍的MSL),确保对方已收到该报文。

CLOSE_WAIT
连接中断被动方的状态。
收到对方的FIN报文后进入该状态,随后发出其最后需要发送的数据。

LAST_ACK
连接中断被动方的状态。
发送完最后需要发送的数据后,最后发送FIN报文,进入该状态,等待对方最后一个ACK报文。

CLOSED
连接中断被动方的状态。
收到对方最后一条ACK后,进入该状态。


关闭主动方的time_wait状态

关闭主动方最后会进入time_wait状态,这一状态会持续2msl。这么做的目的,一是确保对方收到了最后的ack报文;另一方面确保旧连接的报文经过这一时间段后全部作废。


四次挥手可以是三次

这种情况是:关闭被动方最后没有要发的数据了。于是直接把ack报文和fin报文合为一个报文发出。这样关闭主动方收到后,直接从fin_wait1状态变为time_wait状态(跳过了fin_wait2状态)。


连接的半关闭

关闭主动方调用shutdown函数,可以控制将本端的TCP连接的读或写关闭。
int shutdown(int sockfd,int how);
具体关闭方式由参数2来控制。
SHUT_RD :只写不读,接收到的数据会丢弃,不发送fin报文。
SHUT_WR :只读不写,输出缓冲区的数据会丢弃,要发送fin报文。
SHUT_RDWR :相当于调用shutdown两次:首先是以SHUT_RD,然后以SHUT_WR。

shutdown和close的区别:
如果多个进程共享一个套接字,close函数调用一次,套接字的计数引用减去1,为0时才关闭套接字,否则不会关闭套接字。
而shutdown不管引用计数。


进程如何关闭TCP连接?

1、对于客户端来说,一般调用close()来主动关闭连接。即使进程的代码中不调用close()函数,在进程终止时内核会自动关闭所有打开的描述符。

2、对于服务器来说,往往是TCP连接的被动方,不会主动调用close,那么进程需要能及时的感知到套接字的关闭。一般的,当服务器端发现与客户端通信的描述符不可读(读到了fin报文中的文件结束符eof)时,就认为连接关闭,这时候应用层,也就是服务器程序,把最后要发的数据发完,然后主动调用close()关闭这个描述符。

TCP连接的异常关闭

a、b两个正常连接的对端进程。假如b进程没有调用close就异常终止,那么发送FIN包是内核OS代劳,b进程已经不存在,当内核再次收到该socket的消息时,会回应RST报文(因为拥有该socket的进程已经终止)。a进程对收到RST的socket调用write时,内核会给a进程发送SIGPIPE,该信号默认情况下会终止当前a进程。 

注意不管是怎么样描述符是如何被关闭的,都会使内核向描述符的对端发送FIN报文。
TCP连接关闭过程中,除了TIME-WAIT状态外,还有多个关键状态参与了连接的终止流程。以下是这些关键状态的详细解析: 1. **FIN-WAIT-1**:当一方主动关闭连接并发送FIN包后,该方进入FIN-WAIT-1状态。此时,该方已经完成数据发送,等待对方确认收到FIN包的ACK响应[^1]。 2. **FIN-WAIT-2**:在接收到对方的ACK响应后,主动关闭连接的一方进入FIN-WAIT-2状态。此时,主动关闭方仍然可以接收来自对方的数据,但不能再发送新的数据。 3. **CLOSE-WAIT**:被动关闭连接的一方在接收到FIN包后,进入CLOSE-WAIT状态。该状态表示TCP连接已经收到对方的关闭请求,但本地应用程序尚未调用关闭操作。在此状态下,本地端可以继续发送剩余的数据[^2]。 4. **CLOSING**:该状态较为少见,出现在双方同时关闭连接的情况下。当一方发送FIN包后,同时收到对方的FIN包而非ACK响应时,进入CLOSING状态。此时,双方都在等待对方的ACK响应以完成关闭流程[^1]。 5. **LAST-ACK**:当被动关闭连接的一方完成数据发送并发送FIN包后,进入LAST-ACK状态。该状态表示正在等待对方对FIN包的ACK响应,一旦收到该响应,连接将进入CLOSED状态[^1]。 6. **CLOSED**:当连接的两端都完成关闭操作,且所有数据传输和确认过程均已结束,连接进入CLOSED状态。此时,连接完全终止,不再占用系统资源[^2]。 在整个TCP连接关闭过程中,上述状态按照特定的顺序转移,以确保数据的可靠传输和连接的有序终止。这些状态的正确管理对于网络通信的稳定性和可靠性至关重要。 ```python # 示例:模拟TCP连接关闭状态转移 def tcp_connection_close(): # 初始状态为ESTABLISHED(连接已建立) print("Current state: ESTABLISHED") # 主动关闭方发送FIN包,进入FIN-WAIT-1 print("Sent FIN -> Current state: FIN-WAIT-1") # 被动关闭方收到FIN,发送ACK,进入CLOSE-WAIT print("Received FIN, sent ACK -> Current state: CLOSE-WAIT (passive side)") # 主动关闭方收到ACK,进入FIN-WAIT-2 print("Received ACK -> Current state: FIN-WAIT-2") # 被动关闭方完成数据发送,发送FIN,进入LAST-ACK print("Sent FIN -> Current state: LAST-ACK (passive side)") # 主动关闭方收到FIN,发送ACK,进入TIME-WAIT print("Received FIN, sent ACK -> Current state: TIME-WAIT") # 被动关闭方收到ACK,进入CLOSED print("Received ACK -> Current state: CLOSED (passive side)") # 主动关闭方等待2MSL后进入CLOSED print("2MSL timeout -> Current state: CLOSED") tcp_connection_close() ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值