TCP三次握手,四次挥手

本文详细解析了TCP协议中的三次握手建立连接及四次挥手关闭连接的过程。介绍了TCP头部关键字段的作用,如ACK、SYN和FIN,并解释了为何建立连接需要三次握手而关闭连接需要四次挥手。

TCP头部: 其中 ACK   SYN  序号  这三个部分在以下会用到,它们的介绍也在下面。


暂时需要的信息有:

ACK : TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1

SYN(SYNchronization) : 在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1. 因此,  SYN置1就表示这是一个连接请求或连接接受报文。


FIN (finis)即完,终结的意思, 用来释放一个连接。当 FIN = 1 时,表明此报文段的发送方的数据已经发送完毕,并要求释放连接。




三次握手的过程:

首先由Client发出请求连接即 SYN=1 ACK=0  (请看头字段的介绍), TCP规定SYN=1时不能携带数据,但要消耗一个序号,因此声明自己的序号是 seq=x

然后 Server 进行回复确认,即 SYN=1 ACK=1 seq=y, ack=x+1,

再然后 Client 再进行一次确认,但不用SYN 了,这时即为 ACK=1, seq=x+1, ack=y+1.

然后连接建立,为什么要进行三次握手呢(两次确认)。



下面是释放连接的过程:



当客户A 没有东西要发送时就要释放 A 这边的连接,A会发送一个报文(没有数据),其中 FIN 设置为1,  服务器B收到后会给应用程序一个信,这时A那边的连接已经关闭,即A不再发送信息(但仍可接收信息)。  A收到B的确认后进入等待状态,等待B请求释放连接, B数据发送完成后就向A请求连接释放,也是用FIN=1 表示, 并且用 ack = u+1(如图), A收到后回复一个确认信息,并进入 TIME_WAIT 状态, 等待 2MSL 时间。

为什么要等待呢?

为了这种情况: B向A发送 FIN = 1 的释放连接请求,但这个报文丢失了, A没有接到不会发送确认信息, B 超时会重传,这时A在 WAIT_TIME 还能够接收到这个请求,这时再回复一个确认就行了。(A收到 FIN = 1 的请求后 WAIT_TIME会重新记时)


另外服务器B存在一个保活状态,即如果A突然故障死机了,那B那边的连接资源什么时候能释放呢?  就是保活时间到了后,B会发送探测信息, 以决定是否释放连接。

【注意】中断连接端可以是Client端,也可以是Server端。

假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!

整个过程Client端所经历的状态如下:


而Server端所经历的过程如下:


【注意】 在TIME_WAIT状态中,如果TCP client端最后一次发送的ACK丢失了,它将重新发送。TIME_WAIT状态中所需要的时间是依赖于实现方法的。典型的值为30秒、1分钟和2分钟。等待之后连接正式关闭,并且所有的资源(包括端口号)都被释放。

【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。

### TCP 三次握手四次挥手的过程及原理 #### 一、TCP 三次握手过程及原理 TCP 是一种面向连接的可靠传输协议,在数据传输前需要通过三次握手来建立连接。以下是其具体过程: 1. **第一次握手** 客户端向服务器发起连接请求,发送一个带有 SYN 标志位的数据包,并随机生成一个初始序列号 `Seq=x`,此时客户端进入 `SYN_SENT` 状态[^5]。 2. **第二次握手** 服务器收到客户端的 SYN 请求后,返回一个确认消息,该消息同时携带两个标志位:SYN 和 ACK。其中,SYN 表示同意建立连接并随机生成自己的初始序列号 `Seq=y`;ACK 则是对客户端序列号的确认,即 `Ack=x+1`。此时服务器进入 `SYN_RCVD` 状态[^4]。 3. **第三次握手** 客户端收到服务器的响应后,再次发送一个确认消息给服务器,此消息仅带有一个 ACK 标志位,用于确认服务器的序列号,即 `Ack=y+1`。随后,客户端进入 `ESTABLISHED` 状态,而服务器在接收到这个 ACK 后也进入 `ESTABLISHED` 状态,至此完成三次握手[^1]。 通过以上三个步骤,双方不仅建立了连接,还同步了各自的序列号和确认号,从而确保后续通信的可靠性[^3]。 --- #### 二、TCP 四次挥手过程及原理 由于 TCP 协议采用全双工模式工作,因此关闭连接时需分别处理双向通道的释放问题,这通常涉及四个阶段的操作,称为“四次挥手”。 1. **第一次挥手** 主动关闭的一方(通常是客户端)发送 FIN 报文通知对方自己已经没有数据要发送了,同时终止本方向上的数据流。此时,主动关闭方进入 `FIN_WAIT_1` 状态[^2]。 2. **第二次挥手** 被动关闭一方(通常是服务器)收到 FIN 报文后,回应一个 ACK 报文作为确认,设置 `Ack=seq+1`,并将被动关闭方的状态改为 `CLOSE_WAIT`。与此同时,主动关闭方则转变为 `FIN_WAIT_2` 状态[^4]。 3. **第三次挥手** 当被关闭方也没有更多数据待发时,它会再发送一个 FIN 报文告知主动关闭方准备完全断开连接。此时,被动关闭方变为 `LAST_ACK` 状态[^5]。 4. **第四次挥手** 主动关闭方接收到来自被动关闭方的 FIN 报文之后,回复最后一个 ACK 报文予以确认,然后进入 `TIME_WAIT` 状态。经过一段时间延迟(一般为两倍最大分组生存时间 MSL),如果未检测到异常情况,则正式关闭连接并转入 `CLOSED` 状态。同样地,被动关闭方在接受到最终 ACK 报文后立即切换至 `CLOSED` 状态,结束整个流程[^3]。 值得注意的是,“四次挥手”的核心在于允许两端独立管理各自方向上的资源回收,保障任何尚未送达的信息能够得到妥善处理[^2]。 --- ```python # Python模拟TCP三次握手四次挥手逻辑示意 class TCPSession: def __init__(self, client_seq, server_seq): self.client_seq = client_seq self.server_seq = server_seq def three_way_handshake(self): print(f"Client -> Server: SYN Seq={self.client_seq}") self.client_seq += 1 print(f"Server <- Client: SYN+ACK Ack={self.client_seq} Seq={self.server_seq}") self.server_seq += 1 print(f"Client -> Server: ACK Ack={self.server_seq}") def four_way_wavehand(self): print(f"Client -> Server: FIN Seq={self.client_seq}") print(f"Server <- Client: ACK Ack={self.client_seq + 1}") print(f"Server -> Client: FIN Seq={self.server_seq}") print(f"Client <- Server: ACK Ack={self.server_seq + 1}") session = TCPSession(0, 0) print("\n--- Three-Way Handshake ---") session.three_way_handshake() print("\n--- Four-Way Wavehand ---") session.four_way_wavehand() ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值