TCP建立连接和断开连接流程

TCP连接与断开机制
本文详细解析了TCP协议的连接建立(三次握手)及断开(四次挥手)过程,阐述了SYN、ACK、FIN包的作用及TIME_WAIT状态的重要性。

一、基本描述

TCP协议为提供面向连接的服务,需要先建立连接,然后才可以通信,通信结束时,需要断开连接。

二、建立连接流程

建立连接的过程也叫做三次握手,流程如下:

这里写图片描述

1、首先,一定是由客户端发起连接请求,服务端来接收连接请求。客户端发起连接请求后,会先给服务端发送一个SYN包。

2、服务端收到SYN包,会回复SYN的ACK,同时再回复SYN,但SYN和ACK是一起发送的。

客户端收到了SYN+ACK包,完成了客户端到服务端单向连接的建立,然后给服务端回复ACK包。

3、服务端收到客户端发来的ACK包,完成了服务端到客户端单向连接的建立。

说明:

 SYN包会报告TCP需要用到的一些参数。
 服务器在收到SYN后,会将连接放入SyncQueue里(Linux默认2048)。
 服务器在收到ACK后,会将连接放入AcceptQueue里(Linux最大128,应用层可以传入backlog,两者的较小值为AcceptQueue的最大长度)。     

三、断开连接流程

断开连接的过程也叫四次挥手,流程如下:

这里写图片描述

1、断开连接时,发起方可以是客户端也可以是服务端。发起方会先发送一个FIN包,就进入FIN_WAIT_1状态,此时就不能发送用户数据,等待响应方回复ACK。

2、响应方收到FIN包后,就给发起方回复ACK。此时,响应方进入CLOSE_WAIT状态,因为响应方还有待发送的数据,需要等待发送完毕,才能关闭连接(发起方在发送FIN前,会保证已经发送完数据)。

3、发起方收到ACK后,就进入FIN_WAIT_2。此时还能继续接收数据,直到收到响应方的FIN。

4、响应方等数据发送完毕后,就给发起方发送FIN包。

5、发起方收到响应方的FIN包后,就进入TIME_WAIT状态。

6、响应方收到ACK后,就进入CLOSED状态,完成了断开流程。

7、发起方的TIME_WAIT状态会持续2MSL(最大报文生存时间)。然后,进入到CLOSED。

四、为何建立连接是三次握手,而断开连接需要四次挥手?

1、下图是TCP协议头的结构:

这里写图片描述 
里面有专门的位来标记SYN包,FIN包,ACK序号是否有效。

2、三次握手时的SYN和ACK,是可以通过一个TCP包来发送的。

3、四次挥手时为何没有将SYN和ACK一起发送,是因为响应方还有待发送的数据,需要等数据发送完成才能发送SYN包。

五、为何需要TIME_WAIT状态?

1、一个重要的原因是在发起方发送了ACK后,不能保证响应方一定能收到ACK。响应方在发送FIN后,就等待发起方的ACK,在等待一段时间后,如果没有收到ACK,就会重发FIN包。发起方在TIME_WAIT的时间内(等待ACK的时间+重发FIN最大需要2MSL),如果又收到了响应方的FIN包,就会再发ACK包。

### TCP连接建立断开过程的练习题及答案 #### 练习题1:三次握手的过程描述 题目要求解释TCP三次握手中的每一个阶段,并说明其作用。 答案: 当客户端希望与服务端建立TCP连接时,会经历三个主要阶段来完成这一目标: - **第一次握手**:客户端向服务器发送带有SYN标志位的数据包,表示建立连接并同步序列号。此时客户端处于SYN_SENT状态[^3]。 - **第二次握手**:服务器收到SYN后回应一个ACK确认消息给客户端,同时附带自己的初始序列号(也即SYN),这被称为SYN/ACK报文。服务器现在处于SYN_RCVD状态[^1]。 - **第三次握手**:最后,客户端再次回复一个ACK给服务器作为最终确认,之后双方都可以开始正常的数据传输了。这时两端均进入了ESTABLISHED状态。 ```python # Python伪代码模拟三次握手流程 class TCPSession: def __init__(self, client_ip, server_ip): self.client_state = "CLOSED" self.server_state = "LISTEN" def first_handshake(self): if self.client_state == "CLOSED": print(f"{client_ip} -> {server_ip}: SYN") self.client_state = "SYN_SENT" def second_handshake(self): if self.server_state == "LISTEN": print(f"{server_ip} <- {client_ip}: ACK(SYN)") self.server_state = "SYN_RCVD" def third_handshake(self): if self.client_state == "SYN_SENT" and self.server_state == "SYN_RCVD": print(f"{client_ip} -> {server_ip}: ACK") self.client_state = "ESTABLISHED" self.server_state = "ESTABLISHED" ``` #### 练习题2:四次挥手的理解 题目询问为什么关闭TCP连接需要四个步骤而不是像建立那样只需要三步? 答案: 这是因为每个方向上的数据流都需要被单独地关闭,在结束通信前必须确保所有已发送的数据都被对方成功接收到了。因此,每一方都会发出FIN标志位的通知另一方自己不再有更多数据要发出了;而接受到这个通知的一方则需要用ACK来进行确认。整个过程中涉及到两个独立的方向上分别进行这样的操作,所以总共会有四次交互才能完全释放资源。 ```plaintext Client (A) Server (B) | | |---- FIN(No more data from A) -----> | | |-- Enter CLOSE_WAIT state |<--- ACK(FIN received by B) ---------| |-- Enter FIN_WAIT_2 state | | | | |---- FIN(B has no more data too) ---> |<--- ACK(A confirms receipt of B's FIN)-| |-- Enter TIME_WAIT state | |--------------------------------------| ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值