c++ tcp的三次握手

TCP 三次握手(一次性讲透,面试版,结合工控Qt网络场景)

一句话本质

TCP 是可靠的、面向连接的协议。三次握手核心目的:双向确认收发能力,协商初始序列号ISN,建立连接。

简单大白话:

客户端 ↔ 服务端,要互相确认两件事:我能发消息给你,我也能收到你的消息。

一次握手只能单向验证,需要来回3次报文,完成双向确认。

角色约定:

• 客户端(Client):主动发起连接(比如你的Qt程序去连接工控设备服务端)

• 服务端(Server):监听端口,等待连接

📩三步完整流程

第1次握手:客户端 → 服务端 【SYN】

客户端:SYN报文,携带客户端初始序列号 ISN(c)

含义:客户端说:我想和你建立连接,我的消息编号从 ISN(c) 开始

客户端状态:CLOSED → SYN_SENT

服务端收到后状态:LISTEN → SYN_RCVD

SYN(Synchronize):同步序列号标志位

第2次握手:服务端 → 客户端 【SYN + ACK】

服务端回复一个报文同时带两个标记

  1. SYN:服务端自己的初始序列号 ISN(s)

  2. ACK:确认客户端的SYN,确认号 = ISN(c)+1

含义:服务端说:收到你的请求了!我这边也准备好,我的编号从ISN(s)开始;我确认收到了你第ISN(c)号包

✅到这里:服务端确认两件事:客户端能发消息给我、我能收到客户端消息

但是!客户端还不知道:服务端能不能收到我发的ACK,连接还不能建立。

第3次握手:客户端 → 服务端 【ACK】

客户端发送ACK报文,确认号 = ISN(s)+1

含义:客户端说:收到你的SYN消息,确认你的序列号。

✅收到这个ACK之后:

服务端:SYN_RCVD → ESTABLISHED(连接成功)

客户端收到服务端的SYN+ACK之后就已经进入 ESTABLISHED,发送完第三次ACK,连接双向就绪,可以收发业务数据。

👉重点:第三次ACK报文可以携带业务数据(部分操作系统支持),但是一般不会放;SYN报文不能携带数据

✅核心结论:为什么是3次,不是2次?(面试必考题)

假设只握手2次:

客户端发SYN → 服务端回复SYN+ACK,服务端单方面认为连接建立,直接准备资源。

会有经典的失效SYN报文问题:

网络延迟的旧连接请求,到达服务端,两次握手后服务端建立连接、分配内存;但是客户端早就放弃这个连接了,不会发数据。服务端白白占用端口和内存资源,造成资源浪费。

三次握手,必须客户端最后发ACK确认,服务端收到ACK才正式完成连接,规避这个问题。

一句话记:两次握手,服务端无法确认「客户端能不能收到我的消息」。

序列号 ISN 是干嘛的?

TCP是字节流,每个字节都有序列号:

  1. 用来排序:网络乱序到达的数据包,接收端按序列号重组

  2. 去重:网络重复投递的包,用序列号识别丢弃

初始ISN不是固定0,是随机生成,防止网络嗅探、序列号预测攻击。

🧩和你Qt工控开发相关的实际理解

Qt QTcpSocket:

  1. socket->connectToHost() 底层就是发出第一次SYN;

  2. 服务端QTcpServer收到SYN,内核回复SYN+ACK(第二次握手);

  3. 客户端内核发出ACK(第三次握手);

  4. 三次握手全部完成后,Qt才会触发connected()信号。

注意:三次握手是操作系统内核TCP协议栈完成的,不是Qt应用层代码做的。你的Qt代码感知不到SYN报文,只能收到连接成功信号。

📌面试高频坑点

  1. Q:第三次握手丢包会怎么样?

A:服务端没收到ACK,不会进入ESTABLISHED,会超时重传【SYN+ACK】;如果多次重传失败,服务端释放资源。客户端这边已经认为连接建立了,后续发业务包,服务端会回复RST重置。

  1. Q:SYN、ACK是什么?

A:TCP头部的标志位,1表示开启。

• SYN=1:同步序列号,用于发起连接

• ACK=1:确认号有效,代表应答报文

  1. Q:三次握手可以传数据吗?

SY报文(1、2次握手)不允许携带数据;第三次握手ACK报文,协议允许携带业务数据,但是工程上一般不带。

配套对比:TCP四次挥手(顺带区分,面试经常一起问)

握手:建立连接,双向同步序列号,3次

挥手:断开连接,TCP是全双工,双方各自关闭发送通道,4次

极简记忆口诀

  1. 客:SYN,我要连你(1次)

  2. 服:SYN+ACK,收到!我也准备好(2次)

  3. 客:ACK,收到你的消息,连接就绪(3次)

相关推荐
张小姐的猫1 小时前
【AI大模型接入SDK】 —— Ollama本地接入Deepseek
java·linux·开发语言·网络·c++·人工智能
wabs6661 小时前
关于二叉树【力扣116.填充每个节点的下一个右侧节点指针的思考】
数据结构·c++·算法·leetcode·二叉树·层序遍历
David猪大卫10 小时前
【C++修炼】智能指针使用及原理
开发语言·c++·经验分享·笔记·学习·考研·面试
零衣贰11 小时前
The 2026 ICPC Asia East Continent Online Contest (I) 题解
c++·icpc
fpcc12 小时前
c++编程实践—统一初始化
服务器·c++
Zenova EdgeOS13 小时前
C++ 工业边缘 libcurl HTTP 客户端实战
开发语言·c++·网络协议·边缘计算
Jackson_GJH13 小时前
Qt 右键自定义菜单的实现
开发语言·c++·qt
张小姐的猫13 小时前
【AI大模型接入SDK】 —— Gemini接入封装
android·数据结构·数据库·c++·人工智能·python
一木 之林14 小时前
七、一-AI 工程实践、插件化调试与软件交付
java·linux·c++