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次)

相关推荐
朝朝辞暮i几秒前
C++ 第7课 while 循环
开发语言·c++·算法
huanbailu2 小时前
Qt 跨线程信号槽:connect 返回 true 但槽函数不执行的坑
开发语言·c++·qt·信号槽·跨线程·元类型
HEJOO92 小时前
C++ 虚函数表(vtable)深度解析
开发语言·c++
xailorliu3 小时前
矩阵定性-正定负定不定半正定半负定
c++·opencv·线性代数·计算机视觉·矩阵
个 人 练 习 生3 小时前
C++-----string基本使用详解
开发语言·c++·学习
朝朝辞暮i3 小时前
C++ 第 5 课:else if + 多条件判断 + && / || / !
开发语言·c++
千谦阙听4 小时前
【C++篇】:string类——常用接口、底层原理与深浅拷贝
开发语言·c++·学习·visual studio
特立独行的猫A4 小时前
c++的`std::future` 与 `std::promise` 简明教程(5分钟读完)
c++
特立独行的猫A4 小时前
C++ 异步编程:std::future 与 std::promise 详解(含 RPC 客户端实现实践)
c++·后端
All for pursuit.4 小时前
【分治-2】215.数组中的第K个最大元素
数据结构·c++·算法·leetcode