当前位置: 首页 > article >正文

TCP 三次握手与四次挥手:构建与终止可靠通信的核心机制

引言

TCP(传输控制协议)是网络通信的基石,其核心目标是:

        在不可靠的IP层之上提供可靠的数据传输

        为实现这一目标,TCP通过 三次握手(Three-way Handshake)建立连接,通过四次挥手(Four-way Handshake) 终止连接。本期文章我将以通俗易懂的方式解析这两个关键过程的技术细节,并探讨其设计背后的逻辑。


一、三次握手:建立可靠通信信道

1 TCP 报文标志

        TCP 协议就像两个人打电话,需要一些“暗号”来协调对话的开始、结束和确认。这些“暗号”就是报文中的标志位,每个标志代表一个特定动作。

1. SYN(Synchronize,同步标志)

  • 作用:打招呼,告诉对方“我要和你建立连接”。
  • 例子:你打电话给朋友,开口说:“喂,能听到吗?”——这就是 SYN
  • 技术细节:携带初始序列号(类似对话的起始编号),用于三次握手的第一步。

2. ACK(Acknowledgment,确认标志)

  • 作用:确认收到对方的消息,回应“我收到了”。
  • 例子:朋友回答:“能听到!”——这就是 ACK
  • 技术细节ACK 必须配合一个确认号(Acknowledgment Number),表示“我期待你下次从这个编号开始发数据”。

2 握手过程分解

三次握手的目标是同步双方的初始序列号(Sequence Number),确认双方的收发能力正常。具体流程如下:

三次握手过程
步骤方向报文标志状态变化核心作用
第一次握手客户端 → 服务端SYN=1,ACK=0,SEQ(顺序号)=x客户端进入SYN_SENT客户端声明自身具备发送能力
第二次握手服务端 → 客户端SYN=1, ACK=1, SEQ=y, ACK=x+1服务端进入SYN_RCVD服务端确认客户端发送能力,声明自身具备收发能力
第三次握手客户端 → 服务端ACK=1, ACK=y+1双方进入ESTABLISHED客户端确认服务端具备收发能力

三次握手的生活例子:打电话确认身份
假设你(客户端)想给朋友(服务端)打电话确认一件事:

第一次握手(SYN):你拨通电话,说:“喂,是老陈吗?”(你发起连接请求)。
第二次握手(SYN-ACK):朋友接听后回答:“是的,我是老陈。你是小梁吗?”(朋友确认你的请求,并反问你的身份)。
第三次握手(ACK):你回答:“对,我是小梁!”(你确认朋友的身份,双方明确彼此身份)。
此时,双方确认了对方的身份和通信能力,可以开始正式对话。

关键点:三次确认确保双方身份和通信能力可靠,避免“假电话”或“听不清”的问题。


如果还听不懂,没关系,下面我再总结一遍三次握手过程:

握手阶段客户端确认内容服务端确认内容
第一次握手仅自身发送能力客户端发送能力 + 自身接收能力
第二次握手双方收发能力客户端发送能力 + 自身接收能力
第三次握手双方信道就绪自身发送能力 + 客户端接收能力
  • 第一次握手
    • 客户端确认内容:客户端就只看看自己有没有本事把消息发出去,比如检查一下自己的网络设置、相关软件是不是能正常发数据等,只关心自己的发送能力。
    • 服务端确认内容:服务端收到客户端发过来的消息后,一方面知道了客户端有发消息的能力,另一方面也看看自己能不能正常接收消息,比如检查自己的接收端口是不是开着,接收数据的程序是不是在正常运行等。
  • 第二次握手
    • 客户端确认内容:客户端收到服务端的回应后,就知道自己能给服务端发消息,服务端也能收到,同时服务端也能给自己回消息,这就确认了双方的收发能力都是正常的。
    • 服务端确认内容:和第一次握手时差不多,还是确认客户端能发消息给自己,同时自己的接收能力也是好的,没有变化。
  • 第三次握手
    • 客户端确认内容:客户端发送消息给服务端,就是告诉服务端 “我这边一切准备就绪啦,咱们可以开始正式通信啦”,表明双方的通信信道都准备好了,可以正常传输数据了。
    • 服务端确认内容:服务端收到客户端的这个消息后,就知道客户端已经准备好接收数据了,同时也再次确认自己给客户端发消息的能力是没问题的,这样双方就可以正式开始进行数据交互了。


关键设计解析

  • 为什么需要三次而非两次?
    若仅两次握手,服务端无法确认客户端是否收到自己的SYN-ACK。若客户端未收到此包,服务端会持续等待,导致资源浪费(如半连接队列堆积)。三次握手确保双方均确认对方的收发能力。(全双工通信

  • 半连接队列(SYN Queue)与全连接队列(Accept Queue)

    • 半连接队列:存储未完成三次握手的连接(SYN_RCVD状态),用于防御SYN Flood攻击(通过限制队列大小)。
    • 全连接队列:存储已完成握手的连接(ESTABLISHED状态),等待应用调用accept()处理。
  • 第三次握手可携带数据
    客户端在第三次握手时即可发送数据(如HTTP请求),而服务端需完成第三次握手后才能发送数据。这一设计优化了通信效率。


二、四次挥手:优雅终止全双工连接

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,被动方关闭确认最终关闭

2 四次挥手的生活例子:礼貌结束对话

假设你和同事在会议室讨论工作,结束后需要离开:

  1. 第一次挥手(FIN):你说:“我的部分讲完了,我先走了。”(你主动提出结束对话)。
  2. 第二次挥手(ACK):同事回答:“好的,我知道了。”(同事确认你的结束请求,但可能还有话要说)。
  3. 第三次挥手(FIN):同事补充:“对了,下周的会议时间别忘了!”(同事完成自己的发言后,也提出结束对话)。
  4. 第四次挥手(ACK):你回答:“没问题,我会记住的!”(你确认同事的结束请求)。
    至此,双方都确认对话结束,各自离开会议室。

关键点

  • 双方需独立确认结束,因为可能各自有未说完的内容(类似TCP的全双工特性)。
  • 最后你等待片刻(类似TIME_WAIT状态),确保同事没有突然回头补充内容(防止数据丢失)。

关键设计解析

  • 为什么需要四次挥手?
    被动关闭方可能在收到FIN后仍有数据待发送(如服务器需发送最后响应),因此需将ACKFIN分开发送。

  • TIME_WAIT状态的意义

    • 确保最后一个ACK到达:若该ACK丢失,被动方会重传FIN,主动方可再次响应。
    • 防止旧连接数据干扰:等待2MSL(报文最大生存时间,通常60秒)确保网络中残留的旧报文失效。
  • CLOSE_WAIT状态积压问题
    若程序未正确调用close(),会导致大量连接滞留CLOSE_WAIT状态,引发资源泄漏。需通过代码审查或监控工具排查。

三、总结

通过生活化的例子,可以直观理解:

  • 三次握手是“建立信任”的过程,确保双方能正常通信。
  • 四次挥手是“礼貌告别”的过程,确保双方数据完整传输后终止连接。
    这种机制保障了TCP协议在不可靠的网络环境中实现可靠传输。

码字不易,希望可以一键三连,我们下期文章再见!!!


http://www.kler.cn/a/554545.html

相关文章:

  • 调用click.getchar()时Windows PyCharm无法模拟键盘输入
  • RT-Thread+STM32L475VET6实现红外遥控实验
  • HTTP请求状态码
  • RV1126解码—ffmpeg_read_thread线程的讲解
  • 什么是pytest.ini及如何在Pytest中应用以提升配置效率
  • 万能头文件
  • Profinet 转 EtherNet/IP 如何解锁西门子 1500 与罗克韦尔 PLC 通讯潜能
  • Emacs折腾日记(十三)——函数、宏以及命令
  • java每日精进 2.13 MySql迁移人大金仓
  • uniapp 使用unplugin-auto-import 后, vue文件报红问题
  • 一文讲清 AIO BIO NIO的区别
  • hive迁移补数脚本细粒度 表名-分区唯一键
  • Linux内核实时机制7 - 实时改造机理 -软中断优化上
  • php 系统命令执行及绕过
  • shell编程总结
  • 树莓派4基于Debian GNU/Linux 12 (Bookworm)添加多个静态ipv4网络
  • 设计模式教程:享元模式(Flyweight Pattern)
  • 实时股票行情接口与WebSocket行情接口的应用
  • python中格式化输出知识点汇总
  • 使用API有效率地管理Dynadot域名,为域名部署DNS安全拓展(DNSSEC)