游乐游手机版
首页/业界动态/文章详情

TCP 三次握手四次挥手:我画了六张图,终于讲清楚了

时间:2026-04-17 07:24
一、先搞清楚:TCP 连接是什么? 很多人把TCP连接想得很玄乎,其实它的本质很实在:通信双方在内核里各自维护了一组状态和缓冲区。所谓建立连接,说白了,就是双方就“我能收到你、你能收到我”这件事,达成一个可靠的共识。 这个过程,全靠数据包头部那几个关键标志位来驱动: SYN —— 我想建立连接 AC

一、先搞清楚:TCP 连接是什么?

很多人把TCP连接想得很玄乎,其实它的本质很实在:通信双方在内核里各自维护了一组状态和缓冲区。所谓建立连接,说白了,就是双方就“我能收到你、你能收到我”这件事,达成一个可靠的共识。

这个过程,全靠数据包头部那几个关键标志位来驱动:

SYN  —— 我想建立连接
ACK  —— 我确认收到了你的包
FIN  —— 我要关闭连接了
RST  —— 直接重置,出问题了

理解了这几个信号,接下来的握手和挥手,就全是逻辑推演了。

二、三次握手:不是仪式,是必要条件

先看完整的流程图解,有个全局印象:

具体来说,这三步是这样的:

第一次握手:客户端主动出击,发送一个SYN包,核心意思是“我想建连接,我的初始序号是x”。发完这个包,客户端自己就进入SYN_SENT状态,开始等待回应。

第二次握手:服务端收到SYN后,如果同意连接,就回一个SYN-ACK包。这个包有两层含义:一是确认客户端的SYN(ACK),二是也发出自己的连接请求(SYN),并带上自己的初始序号y。此时,服务端进入SYN_RCVD状态。

第三次握手:客户端收到服务端的SYN-ACK后,发出最后一个ACK包进行确认。这个ACK包送达后,双方才共同进入ESTABLISHED状态,连接至此正式建立,可以开始传输数据了。

三、灵魂拷问:为什么不能两次握手?

这是面试官最爱追问的问题,也是理解TCP设计精髓的关键。光背“防止已失效的连接请求”不够,得看场景。

想象一个网络延迟极高的场景:客户端发了一个连接请求(SYN),但迟迟没收到回复,于是超时重发了一个新的。那个旧的SYN包其实没丢,只是在网络里“迷路”了。如果TCP设计成两次握手——即服务端收到SYN后,回一个SYN-ACK就直接建立连接——那么当那个“迷路”的旧SYN包很久之后终于到达服务端时,服务端会认为这是一个新的连接请求,直接建立连接并分配资源。

但问题是,客户端那边早就放弃这个旧请求了。结果就是,服务端会一直空等,白白消耗着连接资源。这就是著名的“已失效连接请求”问题。

所以,第三次握手那个ACK至关重要。它让服务端能够确认:“刚才发SYN的那个客户端,确实还在线,并且确实收到了我的回复,真想建立这个连接。”没有这第三次确认,服务端就无法区分当前收到的是一个正常的连接请求,还是一个迟到的、早已失效的旧请求。

四、序列号 seq 是什么?

握手过程中交换的序列号(seq)是干嘛的?它主要有两大使命:保证数据有序检测重复包

你可能会问,为什么不从0开始,非要弄个随机数作为初始序列号(ISN)?这同样是为了应对网络中的“历史遗留问题”。如果每次连接都从0开始序号,那么上一条连接残留在网络中的、序号重叠的“迷路包”,就可能被新连接错误地接收,导致数据混乱。使用随机化的ISN,可以极大降低这种新旧数据包序号冲突的概率,确保连接的独立性。

五、四次挥手:断开连接为什么比建立还麻烦?

断开连接需要四次交互,比建立连接多一步。原因其实很直接:TCP连接是全双工的

建立连接时,双方的目标一致,都是开启通信通道,所以客户端的SYN和服务端的SYN-ACK可以“合并”在一次回复里。

但关闭连接时,情况不同了。“我不再发送数据了”和“我也不再发送数据了”是两个独立的、可能不同步的事件。当客户端发送FIN表示要关闭自己这一侧的发送通道时,服务端可能还有数据没传完。所以,服务端必须先回一个ACK,确认收到了客户端的关闭请求,然后继续发送剩余数据。等所有数据都发送完毕后,服务端再发送自己的FIN,关闭自己这一侧的发送通道。正因为ACK和FIN不能像握手时那样同时发出,所以挥手过程自然就变成了四步。

六、TIME_WAIT 是什么?为什么等 2MSL?

这里是面试的加分项,也是实际运维中经常遇到的“坑”。主动关闭连接的一方(比如客户端,或者主动关闭连接的服务器),在发出最后一个ACK之后,并不会立即进入CLOSED状态,而是会进入一个TIME_WAIT状态,并等待2MSL的时间。

MSL(Maximum Segment Lifetime)指报文在网络中的最大存活时间,Linux下通常默认是60秒。等待2MSL,主要出于两个目的:

1. 确保最后一个ACK能到达对端:如果这个ACK丢失了,被动关闭方(服务端)会重发FIN。等待2MSL给了足够时间让这个重传的FIN到达,客户端可以再次回应ACK,从而保证连接能可靠关闭。 2. 让旧连接的报文彻底消散:等待2MSL时间,足以让这个连接产生的所有报文都在网络中消失,避免它们干扰后续新建的、可能复用相同四元组(源IP、源端口、目的IP、目的端口)的新连接。

生产环境的影响:对于高并发短连接的服务,如果服务器是主动关闭方,就会产生大量处于TIME_WAIT状态的连接,占用大量端口,可能导致新连接因无法绑定端口而失败。常见的解决方案是启用端口复用:

在代码层面,可以设置SO_REUSEADDR套接字选项:

// 服务端启动时设置 SO_REUSEADDR,允许复用 TIME_WAIT 状态的端口
int opt = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

或者在系统层面进行配置:

# 允许 TIME_WAIT 状态的 socket 复用
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse

七、完整状态机:TCP 连接一生经历的所有状态

这张状态转换图值得仔细琢磨。图中清晰地展示了客户端(蓝色路径)和服务端(绿色路径)在连接生命周期中经历的不同状态。两条路径在ESTABLISHED汇合,共享数据传输的时光,又在关闭时于不同的步骤分道扬镳。理解这张图,TCP连接的生命周期就在你脑子里了。

八、用代码验证:亲眼看到状态变化

理论懂了,最好动手验证一下。用几个简单的命令就能观察TCP状态的变化:

# 终端1:启动一个简单的服务端
nc -l 8080

# 终端2:持续查看连接状态(使用ss命令更现代)
ss -tn state established
# 或者使用传统的netstat
# netstat -an | grep 8080

# 终端3:模拟客户端连接
nc 127.0.0.1 8080

# 此时在终端2,能看到 ESTABLISHED 状态的连接
# 在终端3按 Ctrl+C 断开连接后,再观察终端2,能短暂看到 TIME_WAIT 状态

如果想在程序中获取连接状态,可以使用getsockopt

// 用 getsockopt 获取 TCP 连接信息
struct tcp_info info;
socklen_t len = sizeof(info);
getsockopt(fd, IPPROTO_TCP, TCP_INFO, &info, &len);
// info.tcpi_state 就是当前连接状态(数字对应 TCP_ESTABLISHED=1 等)
printf("TCP state: %d\n", info.tcpi_state);

九、高频面试题精析

Q:三次握手中,第三次 ACK 丢失会怎样?

服务端会一直处于SYN_RCVD状态。它会按照TCP的重传机制,多次重传SYN-ACK包(默认最多5次,间隔时间指数级增长)。如果此时客户端已经进入ESTABLISHED并开始发送数据,那么服务端收到数据包后,会“被动”地进入ESTABLISHED状态。如果始终没收到任何确认或数据,服务端最终会超时关闭这个半连接。

Q:为什么四次挥手不能合并成三次?

根本原因在于,服务端收到FIN时,可能还有数据要发送,所以ACK和FIN不能同时发出。但如果服务端在收到FIN时,恰好没有数据要发送了,那么它完全可以将ACK和自己的FIN合并成一个包发送,这就变成了“三次挥手”。Linux的延迟确认(Delayed ACK)机制有时就会促成这种合并。

Q:SYN Flood攻击是怎么利用握手过程的?

攻击者疯狂发送SYN包,但不回复服务端回应的SYN-ACK,导致服务端维护的半连接队列(SYN_RCVD状态)被占满,无法处理正常的连接请求。防御方法之一是开启SYN Cookie:服务端收到SYN后,不立即分配资源,而是生成一个特殊的序列号(Cookie)放在SYN-ACK中;只有收到携带正确Cookie的ACK时,才正式分配资源建立连接。

Q:close()和shutdown()触发挥手有什么区别?

close()减少文件描述符的引用计数,只有当计数归零时,才会触发TCP的关闭流程(发送FIN)。如果这个套接字被dup()复制过,调用一次close()并不会真正关闭连接。shutdown(fd, SHUT_WR)则不同,它会立即触发TCP的关闭流程,向对端发送FIN,而不管引用计数是多少。因此,想要可靠地、立即地发起四次挥手,应该使用shutdown()

十、一图总结:三次握手 vs 四次挥手

十一、结语

说到底,TCP三次握手和四次挥手的每一步设计,都蕴含着对网络不可靠性的深刻理解和严谨应对:

  • 三次握手,是在最小交互次数下,确保双向通信通道的可靠建立。
  • 四次挥手,是由于全双工通信的特性,两个方向的关闭需要独立确认。
  • TIME_WAIT状态,则是为了最后一个ACK的可靠交付,以及让旧连接的“幽灵”报文彻底消失,为新连接扫清道路。

把这些逻辑理清楚,下次再面对面试官,你就不再是背诵课本答案,而是可以清晰地画出状态图,讲出每一步背后的“为什么”。这才是真正掌握了TCP连接的核心。

来源:https://www.51cto.com/article/839867.html
上一篇MySQL 8.4 运维实录:三个案例带你吃透 MySQL 并行查询,大表扫描不再头大 下一篇合规倒计时:你的车联网靶场有效吗?
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
Steam Deck Beta更新提升Steam Machine兼容性
业界动态 · 2026-07-01

Steam Deck Beta更新提升Steam Machine兼容性

7 月 1 日消息, Valve 近日面向预览版与 Beta 测试通道推送了新一轮 Steam Deck 客户端更新,本次更新的核心目标是全面提升 Steam Machine 的兼容性。换言之,之前那些热衷于客厅游戏主机的老玩家,现在可以在 Steam Deck 系统内更流畅地运行相关游戏内容了。

恋与深空终止新男主开发,专注现有角色体验优化
业界动态 · 2026-07-01

恋与深空终止新男主开发,专注现有角色体验优化

恋与深空宣布终止新男主开发,后续版本不再新增角色,原定6 0版本玩法优化正常实装。团队重心转向现有五位男主角,稳定更新主线剧情并深挖角色故事,提升情感体验与陪伴感,全服发放30次深空许愿券。

索尼DualSense Icon Blue特别版手柄2026年8月6日发售
业界动态 · 2026-07-01

索尼DualSense Icon Blue特别版手柄2026年8月6日发售

索尼 PlayStation 日本官方渠道近日正式揭晓了新一代 DualSense® 无线控制器——Icon Blue 特别版,该限量产品计划于 2026 年 8 月 6 日全面发售。预购通道自 2026 年 6 月 30 日起已分批开放,玩家可尽早锁定。这款手柄采用限量发售策略,外观上运用了极具辨

欧洲热销的移动空调为何在中国难觅踪影
业界动态 · 2026-07-01

欧洲热销的移动空调为何在中国难觅踪影

今夏极端高温天气持续席卷欧洲多国,区域降温需求大幅攀升。从市场走势来看,美的、海尔、海信、长虹、TCL等国内主流家电企业积极布局欧洲市场,尤其是推出的移动空调产品,凭借适配性优势持续抢占欧洲市场份额,多款产品出现缺货售罄的热销局面。这类在欧洲成为刚需的降温家电,在国内市场却始终处于小众地位,终端普及

小米首款NAS智能存储双盘位4K HDMI AI相册众筹2299元
业界动态 · 2026-07-01

小米首款NAS智能存储双盘位4K HDMI AI相册众筹2299元

小米首款NAS智能存储发布,双盘位最大60TB,配4GB内存、32GB存储、2 5G网口。集成AI相册、四路监控、微信备份,支持16账户,2299元起众筹,海康代工,面向家庭用户。