首页 游戏 软件 资讯 排行榜 专题
首页
业界动态
TCP 三次握手四次挥手:我画了六张图,终于讲清楚了

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

热心网友
55
转载
2026-04-17

一、先搞清楚: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
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

燕云十六声天工地窟身如飞燕宝箱获取全攻略
游戏资讯
燕云十六声天工地窟身如飞燕宝箱获取全攻略

在《燕云十六声》的天工地窟中,“身如飞燕”宝箱的获取是一场对玩家综合探索能力的深度考验。想要成功开启它,不仅需要耐心与观察力,更需掌握系统性的探索策略。 掌握地窟地形与核心布局 进入天工地窟后,首要任务是进行全方位的地形勘察。建议玩家先熟悉主要通道、分支岔路以及所有可能被忽略的角落,建立完整的地图认

热心网友
05.18
2026年家装设计软件推荐:高人气实用工具精选指南
游戏资讯
2026年家装设计软件推荐:高人气实用工具精选指南

装修这件事,说多了都是泪。找施工队像开盲盒,预算表永远在“动态调整”,设计图看得眼花缭乱……投入大量时间和精力,最后的效果可能还是差强人意。说到底,信息不对称和过程不透明,是大多数装修烦恼的根源。 好在,如今有不少专业的数字化工具,能帮我们把控关键环节。今天就来聊聊五款定位清晰、实用性强的装修类应用

热心网友
05.18
燕云十六声山洞奇遇任务全流程攻略与解法详解
游戏资讯
燕云十六声山洞奇遇任务全流程攻略与解法详解

在《燕云十六声》的宏大江湖中,“不见山洞”无疑是一处引人入胜的秘境。这里不仅栖息着珍奇异兽、埋藏着稀世珍宝,更交织着无数待玩家发掘的隐秘故事与特殊事件。若想彻底揭开此地的所有秘密,掌握以下探索技巧至关重要。 进入不见山洞后,首要任务是保持专注,对环境进行细致勘察。洞内的景象暗藏玄机,绝非一目了然。一

热心网友
05.18
骷髅传奇神盾系统玩法详解与获取攻略
游戏资讯
骷髅传奇神盾系统玩法详解与获取攻略

在《骷髅传奇》中,神盾系统是决定角色战力的核心模块,远非一件普通装备可比。它更像是一位能够深度定制、伴随你征战四方的忠实伙伴。本文将为你全面解析神盾系统的获取、培养与实战运用,助你将其从基础配置打造为真正的战力引擎,在游戏中脱颖而出。 获取你的第一面神盾是旅程的起点。游戏内提供了多样化的获取途径:完

热心网友
05.18
和平精英孙悟空皮肤获取与实战技巧全解析
游戏资讯
和平精英孙悟空皮肤获取与实战技巧全解析

天成孙悟空这款限定皮肤,以其独特的视觉设计在战场上脱颖而出。它将中国古典神话中齐天大圣的经典形象,与游戏内的现代美学风格进行了深度结合。标志性的金色毛发、可化为武器的金箍棒特效,以及服饰上精致的云纹与神话元素,共同塑造了一个极具战场辨识度的英雄形象。这种高辨识度本身,在战术层面就具有独特价值——它能

热心网友
05.18