tcp的三次握手与四次挥手简介
🔹 一、TCP 三次握手 (建立连接)
目的: 建立可靠的全双工通信,确认双方的收发能力正常。
步骤
第一次握手:
客户端发送 SYN=1,Seq=x 到服务器,请求建立连接。
表示“我要和你建立连接,我的初始序列号是
x
”。
第二次握手:
服务器收到后,回复 SYN=1,ACK=1,Seq=y,Ack=x+1。
表示“我同意建立连接,我的初始序列号是
y
,并确认你发送的序号x
”。
第三次握手:
客户端收到后,再发 ACK=1,Seq=x+1,Ack=y+1 给服务器。
表示“我确认你发送的序号
y
”。
✅ 连接建立成功,双方进入 ESTABLISHED 状态。
三次握手图解
Client Server| --------- SYN, Seq=x -----------> || <---- SYN, ACK, Seq=y, Ack=x+1 -- || ---- ACK, Seq=x+1, Ack=y+1 -----> |
🔹 二、TCP 四次挥手 (断开连接)
目的: 释放全双工连接,双方都能正常结束通信。
步骤
第一次挥手:
客户端发送 FIN=1,Seq=u,进入 FIN_WAIT_1 状态。
表示“我不再发送数据了,但还能接收”。
第二次挥手:
服务器收到后,回复 ACK=1,Ack=u+1,进入 CLOSE_WAIT 状态。
表示“我知道了,但我可能还有数据要发”。
客户端进入 FIN_WAIT_2 状态。
第三次挥手:
服务器数据发完后,发送 FIN=1,Seq=v,进入 LAST_ACK 状态。
表示“我也不发了”。
第四次挥手:
客户端收到后,回复 ACK=1,Ack=v+1,进入 TIME_WAIT 状态。
等待一段时间(通常是 2MSL),确保服务器收到了最后的 ACK。
然后客户端进入 CLOSED 状态,连接彻底释放。
四次挥手图解
Client Server| -------- FIN, Seq=u -----------> || <----------- ACK, Ack=u+1 -------|| <-------- FIN, Seq=v ------------|| --------- ACK, Ack=v+1 --------> |
🔹 为什么握手是 3 次,而挥手是 4 次?
建立连接时,服务端可以把 SYN 和 ACK 合并在一个报文中发出,所以只需要三次。
关闭连接时,服务端可能还有数据没发完,必须先回 ACK,再等数据发完后再发 FIN,不能合并,所以需要四次。
🔹 为什么要3次握手?为什么要4次挥手?
🔹 为什么要三次握手?
👉 类比:打电话前的确认
第一次握手(客户端 → 服务端)
小明拨通电话,对小红说:
“喂,你能听到我吗?”第二次握手(服务端 → 客户端)
小红听到了,回答:
“我能听到你,你能听到我吗?”第三次握手(客户端 → 服务端)
小明再回应:
“我也能听到你。”
✅ 这样双方都确认了:
小明的声音能到小红;
小红的声音也能到小明。
所以必须要 三次,才能保证 双方都确认收发正常。
如果只有两次,可能会出现“我能听到你,但你没确认你能听到我”,那通信就不可靠了。
🔹 为什么要四次挥手?
👉 类比:挂电话的过程
第一次挥手(客户端 → 服务端)
小明说:
“我这边没啥要说的了,准备挂电话。”第二次挥手(服务端 → 客户端)
小红回应:
“好的,我知道了,但我还有点事要说。”第三次挥手(服务端 → 客户端)
小红终于说完了,补一句:
“我说完了,也可以挂了。”第四次挥手(客户端 → 服务端)
小明确认:
“好的,挂吧。” 然后双方都挂机。
✅ 为什么不是三次?
因为 关闭连接时双方的状态可能不同步:
客户端可能没数据了,但服务端还要再说几句(比如发完剩余的数据)。
所以服务端需要分 两次:先确认收到“我没数据了”,再等自己说完,最后才说“我也没数据了”。
🔹 总结类比
三次握手 = 建立信任的确认环节
就像两个人打电话前,必须确认“你能听到我”和“我也能听到你”。四次挥手 = 礼貌地结束对话
就像挂电话,先一方说“我没事了”,对方说“知道了,我还要说点”,等对方说完,最后再双方确认挂掉。
🔹 为什么说握手两次通信会不可靠?
这个问题问得非常关键 👍,我们说 三次握手不可少,核心就在于——如果只有两次,就有可能出现 “假连接 / 半开连接”,导致不可靠。
🔹 假设只有 两次握手
流程会变成:
客户端 → 服务端:SYN=1,Seq=x
客户端请求连接。服务端 → 客户端:SYN=1,ACK=1,Seq=y,Ack=x+1
服务端同意并确认。
此时,双方就认为连接建立完成。
🔹 问题出现在哪里?
问题是:
服务端虽然告诉了客户端“我能收你的消息”,
但是 客户端从来没告诉服务端“我能收你的消息”。
也就是说,服务端并不知道自己发的消息,客户端能不能正常接收。
🔹 具体场景举例
👉 假设有这样一种情况:
客户端发出第一次握手(SYN包),但在网络中延迟太久。
服务端收到了这个包,立刻回了SYN+ACK(第二次握手)。
可是客户端 突然掉线,根本没收到服务端的回复。
此时:
服务端会以为连接已经建立成功(因为两次就算完成)。
但是客户端根本没进入连接状态。
结果就是:
服务端会一直等客户端的数据,但永远等不到。
占用了资源,还可能导致**SYN洪泛攻击(SYN Flood)**的安全问题。
🔹 三次握手如何解决?
多了第三次握手:
客户端必须回复 ACK(确认自己能收到服务端的消息)。
如果服务端没有收到这个 ACK,就知道客户端出问题了,就不会进入 ESTABLISHED 状态。
✅ 这样就避免了“单方面以为已经建立连接”的不一致问题。
🔹 通俗类比
两次握手:
小明对小红说:“喂,你能听到我吗?”
小红说:“能听到,你能听到我吗?”
—— 如果小明此时突然掉线,小红以为电话打通了,但小明根本不在。三次握手:
小明再确认一句:“嗯,我能听到你。”
—— 双方都确认无误,才算真的连上。