基础
TCP 的完整生命周期可以划分为
三个核心阶段 :建立连接(三次握手)
→
传输数据(可靠传输与流量/拥塞控制) → 断开连接(四次挥手) 。
流程总览:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 客户端 (Client) 服务端 (Server) | | | ------------- 1. SYN (Seq=x) --------------> | (LISTEN) | <------- 2. SYN+ACK (Seq=y, Ack=x+1) ------- | (SYN-RCVD) | ------------- 3. ACK (Ack=y+1) ------------> | (ESTABLISHED) | | |============ 建立连接 (三次握手) ============| | | | -------------- 数据包 (Seq=x+1) -----------> | (接收数据) | <------------- ACK包 (Ack=x+n) ------------- | (确认收到) | | |============ 数据传输 (滑动窗口/重传) =======| | | | ------------- 1. FIN (Seq=u) --------------> | (CLOSE-WAIT) | <------------- 2. ACK (Ack=u+1) ------------ | | <------------- 3. FIN (Seq=v) -------------- | (LAST-ACK) | ------------- 4. ACK (Ack=v+1) ------------> | (CLOSED) | (TIME-WAIT 2MSL) | | (CLOSED) | | | |============ 断开连接 (四次挥手) ============|
阶段 1:连接建立 —— 三次握手(Three-Way Handshake)
目的:
确认双方的接收与发送能力均正常,同步双方的初始序列号(ISN, Initial
Sequence Number),并协商 MSS(最大报文段长度)等参数。
1 第一次握手:SYN(客户端 → 服务端)
具体动作: 客户端向服务端发送 SYN=1
的报文,随机生成一个初始序列号 Seq = x。此时客户端进入
SYN-SENT 状态。
作用: 告诉服务端:“我想建立连接,我的初始序列号是
x”。
2 第二次握手:SYN + ACK(服务端 → 客户端)
具体动作: 服务端收到 SYN 后,回复
SYN=1, ACK=1 报文,确认号
Ack = x + 1,同时自己也随机生成一个初始序列号
Seq = y。此时服务端进入 SYN-RCVD 状态。
作用:
告诉客户端:“收到你的请求了,我同意建立连接,我的初始序列号是 y”。
3 第三次握手:ACK(客户端 → 服务端)
具体动作: 客户端收到服务端的响应后,发送
ACK=1 报文,确认号
Ack = y + 1,自身的序列号变为
Seq = x + 1。此时客户端进入 ESTABLISHED
状态,服务端收到后也进入 ESTABLISHED 状态。
作用:
告诉服务端:“收到你的同意了,连接正式建立!”(此时第三次握手可以携带客户端要发送的数据)。
数据传输 —— 可靠机制与控制(Data Transfer)
连接建立后,双方开始互传数据。TCP
通过以下机制保障“数据不丢失、不重复、按序到达、不冲垮对方和网络”:
按序到达与去重(Seq / Ack 机制):
每个传输的数据包都带有
Sequence Number(序列号),接收方收到后回复
Acknowledgment Number(确认号),告知发送方下一个期待接收的字节序号。如果收到重复包则直接丢弃。
超时重传与快速重传(Retransmission):
超时重传(RTO):
发送方发包后开启计时器,若超过一定时间未接收到
ACK,即判定丢包并重新发送。
快速重传(Fast Retransmissions): 接收方连续收到 3
个相同的冗余 ACK(Dup
ACK),发送方无需等待超时定时器,立即重传丢失的数据包。
流量控制(Flow Control - 滑动窗口):
接收方在 ACK 包中通过 Window Size(窗口大小)
字段实时告知发送方自己当前的接收缓冲区剩余空间,防止发送方发得太快导致接收方缓冲区溢出而丢包。
拥塞控制(Congestion Control):
避免过多数据注入网络导致路由器或链路过载。主要由四大算法控制:慢启动(Slow
Start) 、拥塞避免(Congestion
Avoidance) 、快速重传(Fast Retransmit) 和
快速恢复(Fast
Recovery) 。动态调整拥塞窗口(cwnd)。
连接断开 —— 四次挥手(Four-Way Teardown)
抓包
1 2 3 7 0.022088400 192.168.0.12 223.109.82.212 TCP 66 2993 → 443 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 WS=256 SACK_PERM 8 0.037079300 223.109.82.212 192.168.0.12 TCP 66 443 → 2993 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=1400 WS=32 SACK_PERM 9 0.037355900 192.168.0.12 223.109.82.212 TCP 54 2993 → 443 [ACK] Seq=1 Ack=1 Win=263168 Len=0
TCP 三次握手(连接建立): No. 7 - 9.
数据包 7 到 9 展示了完整的建立过程:
No. 7 :客户端 192.168.0.12:2993 发送
[SYN](Seq=0)。
No. 8 :服务端 223.109.82.212:443 回复
[SYN, ACK](Seq=0, Ack=1)。
No. 9 :客户端回复 [ACK](Seq=1,
Ack=1),TCP 连接成功建立。
验证成功: 第 9 包后,双方 TCP 状态均变为
ESTABLISHED。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 10 0.038365100 192.168.0.12 223.109.82.212 TCP 1454 2993 → 443 [ACK] Seq=1 Ack=1 Win=263168 Len=1400 [TCP PDU reassembled in 11] 11 0.038365100 192.168.0.12 223.109.82.212 TLSv1.2 385 Client Hello (SNI=www.baidu.com) 12 0.064204800 223.109.82.212 192.168.0.12 TCP 60 443 → 2993 [ACK] Seq=1 Ack=1732 Win=82304 Len=0 13 0.066597000 223.109.82.212 192.168.0.12 TLSv1.2 1454 Server Hello 14 0.066597000 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=1401 Ack=1732 Win=82304 Len=1400 [TCP PDU reassembled in 17] 15 0.066878700 192.168.0.12 223.109.82.212 TCP 54 2993 → 443 [ACK] Seq=1732 Ack=2801 Win=263168 Len=0 16 0.067020200 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=2801 Ack=1732 Win=82304 Len=1400 [TCP PDU reassembled in 17] 17 0.067020200 223.109.82.212 192.168.0.12 TLSv1.2 1060 Certificate, Server Key Exchange, Server Hello Done 18 0.067080300 192.168.0.12 223.109.82.212 TCP 54 2993 → 443 [ACK] Seq=1732 Ack=5207 Win=263168 Len=0 19 0.070535400 192.168.0.12 223.109.82.212 TLSv1.2 180 Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message 20 0.071346100 192.168.0.12 223.109.82.212 TLSv1.2 801 Application Data 21 0.080248200 223.109.82.212 192.168.0.12 TCP 1060 [TCP Spurious Retransmission] 443 → 2993 [PSH, ACK] Seq=4201 Ack=1732 Win=82304 Len=1006 22 0.080493500 192.168.0.12 223.109.82.212 TCP 66 [TCP Dup ACK 18#1] 2993 → 443 [ACK] Seq=2605 Ack=5207 Win=263168 Len=0 SLE=4201 SRE=5207 23 0.090828300 223.109.82.212 192.168.0.12 TCP 60 443 → 2993 [ACK] Seq=5207 Ack=1858 Win=82304 Len=0 24 0.091006000 223.109.82.212 192.168.0.12 TLSv1.2 280 New Session Ticket, Change Cipher Spec, Encrypted Handshake Message
TLS 1.2 加密协商: No. 10 - 24.
在 TCP 之上建立 HTTPS 安全通道:
No. 11 :客户端发送
Client Hello(请求访问
[www.baidu.com](https://www.baidu.com))。
No. 13-17 :服务端回复
Server Hello、证书(Certificate)及密钥交换数据。
No. 19 :客户端发送密钥交换(Client Key Exchange)及
Change Cipher Spec。
No. 24 :服务端完成密钥协商,加密通道准备就绪。
验证成功:* 第 24 包后,后续传输全部转为
Application Data 密文。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 25 0.091889000 223.109.82.212 192.168.0.12 TCP 60 443 → 2993 [ACK] Seq=5433 Ack=2605 Win=85120 Len=0 26 0.094859900 223.109.82.212 192.168.0.12 TLSv1.2 1262 Application Data 27 0.095098300 192.168.0.12 223.109.82.212 TCP 54 2993 → 443 [ACK] Seq=2605 Ack=6641 Win=263168 Len=0 28 0.095234600 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=6641 Ack=2605 Win=85120 Len=1400 [TCP PDU reassembled in 29] 29 0.095234600 223.109.82.212 192.168.0.12 TLSv1.2 1454 Application Data 30 0.095234600 223.109.82.212 192.168.0.12 TLSv1.2 1454 Application Data, Application Data, Application Data 31 0.095234600 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=10841 Ack=2605 Win=85120 Len=1400 [TCP PDU reassembled in 32] 32 0.095234600 223.109.82.212 192.168.0.12 TLSv1.2 957 Application Data, Application Data 33 0.095413600 192.168.0.12 223.109.82.212 TCP 54 2993 → 443 [ACK] Seq=2605 Ack=13144 Win=263168 Len=0 34 0.113460200 223.109.82.212 192.168.0.12 TCP 957 [TCP Spurious Retransmission] 443 → 2993 [PSH, ACK] Seq=12241 Ack=2605 Win=85120 Len=903 35 0.113663100 192.168.0.12 223.109.82.212 TCP 66 [TCP Dup ACK 33#1] 2993 → 443 [ACK] Seq=2605 Ack=13144 Win=263168 Len=0 SLE=12241 SRE=13144 36 0.364462700 192.168.0.12 223.109.82.212 TLSv1.2 861 Application Data 37 0.384911800 223.109.82.212 192.168.0.12 TCP 60 443 → 2993 [ACK] Seq=13144 Ack=3412 Win=87936 Len=0 38 0.440156400 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=13144 Ack=3412 Win=87936 Len=1400 [TCP PDU reassembled in 40] 39 0.440156400 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=14544 Ack=3412 Win=87936 Len=1400 [TCP PDU reassembled in 40] 40 0.440156400 223.109.82.212 192.168.0.12 TLSv1.2 1379 Application Data 41 0.440156400 223.109.82.212 192.168.0.12 TLSv1.2 1454 Application Data 42 0.440156400 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=18669 Ack=3412 Win=87936 Len=1400 [TCP PDU reassembled in 49] 43 0.440442600 192.168.0.12 223.109.82.212 TCP 54 2993 → 443 [ACK] Seq=3412 Ack=20069 Win=263168 Len=0 44 0.440573400 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=20069 Ack=3412 Win=87936 Len=1400 [TCP PDU reassembled in 49] 45 0.440573400 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=21469 Ack=3412 Win=87936 Len=1400 [TCP PDU reassembled in 49] 46 0.440573400 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=22869 Ack=3412 Win=87936 Len=1400 [TCP PDU reassembled in 49] 47 0.440573400 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=24269 Ack=3412 Win=87936 Len=1400 [TCP PDU reassembled in 49] 48 0.440573400 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=25669 Ack=3412 Win=87936 Len=1400 [TCP PDU reassembled in 49] 49 0.440573400 223.109.82.212 192.168.0.12 TLSv1.2 1373 Application Data, Application Data 50 0.440689800 192.168.0.12 223.109.82.212 TCP 54 2993 → 443 [ACK] Seq=3412 Ack=28388 Win=263168 Len=0 108 0.692460400 192.168.0.12 223.109.82.212 TLSv1.2 895 Application Data 109 0.712951200 223.109.82.212 192.168.0.12 TCP 60 443 → 2993 [ACK] Seq=28388 Ack=4253 Win=90880 Len=0 124 0.769525600 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=28388 Ack=4253 Win=90880 Len=1400 [TCP PDU reassembled in 125] 125 0.769525600 223.109.82.212 192.168.0.12 TLSv1.2 925 Application Data 126 0.769665400 192.168.0.12 223.109.82.212 TCP 54 2993 → 443 [ACK] Seq=4253 Ack=30659 Win=263168 Len=0
数据交互(HTTP 请求与响应): No. 20 - 126.
网页数据的双向传输:
客户端发送加密请求(如 No. 20, 36, 108)。
服务端分段返回大量网页资源数据(如 No. 28-32, 40-49, 125)。
期间触发了 TCP 选段重传与 SACK 确认(如 No. 21-22,
34-35),反映了真实的动态网络抖动。
1 2 329 15.806560000 223.109.82.212 192.168.0.12 TCP 60 [TCP Keep-Alive] 443 → 2993 [ACK] Seq=30658 Ack=4253 Win=90880 Len=0 330 15.806634000 192.168.0.12 223.109.82.212 TCP 54 [TCP Keep-Alive ACK] 2993 → 443 [ACK] Seq=4253 Ack=30659 Win=263168 Len=0
TCP Keep-Alive 保活探测: No. 329 - 330.
数据传输完成后,连接进入空闲状态:
No. 329 (约第 15.8 秒):服务端向客户端发送
[TCP Keep-Alive] 询问连接是否有效。
No. 330 :客户端网络栈立即响应
[TCP Keep-Alive ACK] 确认在线。
1 2 3 4 5 347 22.117811800 192.168.0.12 223.109.82.212 TCP 54 2993 → 443 [FIN, ACK] Seq=4253 Ack=30659 Win=263168 Len=0 350 22.138313900 223.109.82.212 192.168.0.12 TCP 60 443 → 2993 [ACK] Seq=30659 Ack=4254 Win=90880 Len=0 351 22.138313900 223.109.82.212 192.168.0.12 TLSv1.2 85 Encrypted Alert 352 22.138313900 223.109.82.212 192.168.0.12 TCP 60 443 → 2993 [FIN, ACK] Seq=30690 Ack=4254 Win=90880 Len=0 353 22.138876300 192.168.0.12 223.109.82.212 TCP 54 2993 → 443 [RST, ACK] Seq=4254 Ack=30690 Win=0 Len=0
TCP 四次挥手与关闭(连接终止): No. 347 - 353.
主动关闭标签页或离线后,触发的完整断开流程:
No. 347(第一次挥手) :客户端主动发起断开,发送
[FIN, ACK](Seq=4253, Ack=30659)。
No. 350(第二次挥手) :服务端回复
[ACK](Ack=4254),确认收到客户端的关闭请求。
No. 351-352(第三次挥手) :服务端发送 TLS
告警通知关闭后,随即发送 [FIN, ACK](Seq=30690,
Ack=4254),表示服务端也准备关闭。
No. 353(最终重置/关闭) :客户端收到服务端的 FIN
后,由于本地套接字已彻底关闭,回复
[RST, ACK],将连接直接重置并强制释放资源。
验证成功: 双方彻底清理端口资源,TCP 连接生命周期结束。
总结
Seq(Sequence
Number):我这次发给你的数据,从第几字节开始。
Ack(Acknowledgment
Number):你等会发给我的数据,应该从第几字节开始(代表我在这之前的字节都已经收齐了)。
重传
首先 ACK 表示 这个序号之前的数据已经收齐了
ACK = 1001 连续收到的数据只到 1000
告诉对面从1001开始发送数据过来
SACK Option 记录着 ACK 后面收到的 不连续数据
SACK Option = [4001 ~ 6001], [2001 ~ 3001]
第一块:4001 到 6000
第二块:2001 到 3000
客户端 :“百度,我最远只收到了第 1000
字节,你等会儿发送给我的数据请从 1001
开始(ACK=1001) ;但是你先别急着把 1001 后面的全部重发,因为
2001~3000 和 4001~6000
这两段我已经拿到了,你只把中间空着的那两块给补上就行(SACK
区间) !”
只有建立连接(SYN)、断开连接(FIN)和真实传输数据(Len >
0)才会让 Seq 增加;纯控制包(如纯 ACK、RST)的 Seq
永远保持不动。
数据包Len长度 = 抓包软件Length - 数据链路层 14 字节 - 网络层 20
字节 - 传输层 20 字节
抓包软件Length =
以太网头部 (14B) + IP 头部 (20B) + TCP 头部 (20B) + 实际数据 (331B) = 385B
如果 TCP Header 带有 Options(比如握手时的 MSS、WS 或传输时的 SACK
自身),TCP 头部会大于 20 字节。
ws是窗口缩放因子,握手1 我告诉对面 我的ws,握手2 对面告诉我他的ws
(只有ws相对传递完毕,就是握手3才开始生效,之前都为1)
真正的窗口大小要看数据包具体字段Window: 2572, 抓包工具只会显示
*ws后的数值
字段Window 只有16位 上限64KB 需要WS辅助
软件显示的ws 256
非传输的值。TCP Option - Window scale: 8 (multiply by 256)
实际发送的是8给对面,对面会通过2^8=256得出我这边的ws
TCP PDU reassembled in 11
软件里有这个表示数据包太大,被切分了。数值11
表示最后一个包是在No.11
1 2 3 4 5 6 7 8 9 10 10 0.038365100 192.168.0.12 223.109.82.212 TCP 1454 2993 → 443 [ACK] Seq=1 Ack=1 Win=263168 Len=1400 [TCP PDU reassembled in 11] 11 0.038365100 192.168.0.12 223.109.82.212 TLSv1.2 385 Client Hello (SNI=www.baidu.com) 14 0.066597000 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=1401 Ack=1732 Win=82304 Len=1400 [TCP PDU reassembled in 17] 16 0.067020200 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=2801 Ack=1732 Win=82304 Len=1400 [TCP PDU reassembled in 17] 17 0.067020200 223.109.82.212 192.168.0.12 TLSv1.2 1060 Certificate, Server Key Exchange, Server Hello Done #上面是分包了 下面是未分包 12 0.064204800 223.109.82.212 192.168.0.12 TCP 60 443 → 2993 [ACK] Seq=1 Ack=1732 Win=82304 Len=0 13 0.066597000 223.109.82.212 192.168.0.12 TLSv1.2 1454 Server Hello
tls
Handshake Type: Server Hello (2) 里的
Version: TLS 1.2 (0x0303) 才会最后确定使用的tls
版本。不要被TLSv1.2 Record Layer: Handshake Protocol: Server Hello误导
1 2 10 0.038365100 192.168.0.12 223.109.82.212 TCP 1454 2993 → 443 [ACK] Seq=1 Ack=1 Win=263168 Len=1400 [TCP PDU reassembled in 11] 11 0.038365100 192.168.0.12 223.109.82.212 TLSv1.2 385 Client Hello (SNI=www.baidu.com)
代码/类型 :Client Hello (SNI=[www.baidu.com](https://www.baidu.com))
正在做什么 :你的电脑(192.168.0.12)向百度服务器发起
TLS 加密申请。
告知 SNI :明确指定要访问的域名是
[www.baidu.com](https://www.baidu.com)。
提交算法清单 :把你电脑支持的加密算法组合(Cipher
Suites)、TLS 版本列表发给服务器供其挑选。
发送 Client Random :发送客户端生成的随机数
A(后续用来计算对称密钥)。
里面也包含支持哪些tls版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Transport Layer Security TLSv1.2 Record Layer: Handshake Protocol: Client Hello Handshake Protocol: Client Hello Random: 2a1c5...f3455152786189e22 Extension: supported_versions (len=7) TLS 1.3, TLS 1.2 Cipher Suites (16 suites) Cipher Suite: Reserved (GREASE) (0x2a2a) Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301) Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302) Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030) Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9) Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013) Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014) Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c) Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d) Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f) Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
0
1 2 12 0.064204800 223.109.82.212 192.168.0.12 TCP 60 443 → 2993 [ACK] Seq=1 Ack=1732 Win=82304 Len=0 13 0.066597000 223.109.82.212 192.168.0.12 TLSv1.2 1454 Server Hello
代码/类型 :Server Hello
正在做什么 :百度服务器回应你的申请。
确定算法 :从你刚才提交的清单里选定了一套双方都支持的加密套件(比如
ECDHE-RSA-AES128-GCM-SHA256)。
发送 Server Random :发送服务器生成的随机数
B(后续用来计算对称密钥)。
1 2 3 4 5 Transport Layer Security TLSv1.2 Record Layer: Handshake Protocol: Server Hello Handshake Protocol: Server Hello Random: 6aab8a...d28aa2c Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
0
1 2 3 14 0.066597000 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=1401 Ack=1732 Win=82304 Len=1400 [TCP PDU reassembled in 17] 16 0.067020200 223.109.82.212 192.168.0.12 TCP 1454 443 → 2993 [ACK] Seq=2801 Ack=1732 Win=82304 Len=1400 [TCP PDU reassembled in 17] 17 0.067020200 223.109.82.212 192.168.0.12 TLSv1.2 1060 Certificate, Server Key Exchange, Server Hello Done
代码/类型 :Certificate, Server Key Exchange, Server Hello Done(重组后的复合包)
正在做什么 :服务器把握手所需的核心凭证一次性全塞给你:
Certificate :把百度的
公钥数字证书 发给你,让你校验百度身份的真伪。
Server Key Exchange :发送基于 ECDHE
密钥交换算法的服务器临时公钥参数(用于生成密钥,避免直接在网线上传输密钥)。
Server Hello Done :宣告“服务器端的握手第一阶段信息全部发完了”。
1 2 3 4 5 6 7 8 9 10 11 Transport Layer Security Handshake Protocol: Certificate Certificates (4764 bytes) Certificate Length: 2543 Certificate […]: 308209eb308208....52534120 Transport Layer Security TLSv1.2 Record Layer: Handshake Protocol: Server Key Exchange Handshake Protocol: Server Key Exchange TLSv1.2 Record Layer: Handshake Protocol: Server Hello Done Handshake Protocol: Server Hello Done
0
1 2 18 0.067080300 192.168.0.12 223.109.82.212 TCP 54 2993 → 443 [ACK] Seq=1732 Ack=5207 Win=263168 Len=0 19 0.070535400 192.168.0.12 223.109.82.212 TLSv1.2 180 Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
代码/类型 :Client Key Exchange, Change Cipher Spec, Encrypted Handshake Message
正在做什么 :你的电脑验证证书通过后,完成客户端的最后握手准备:
Client Key Exchange :把客户端的 ECDHE
临时公钥参数发给服务器。此时,双方已各自在本地算出了最终的对称密钥 。
Change Cipher Spec :正式通知服务器:“从下一字节开始,我发的所有包都必须用刚才算好的密钥加密!”
Encrypted Handshake Message(Finished) :发送第一段用新密钥加密的握手验证数据,供对方验证加密是否正常。
1 2 3 4 Transport Layer Security TLSv1.2 Record Layer: Handshake Protocol: Client Key Exchange TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message
0
1 2 23 0.090828300 223.109.82.212 192.168.0.12 TCP 60 443 → 2993 [ACK] Seq=5207 Ack=1858 Win=82304 Len=0 24 0.091006000 223.109.82.212 192.168.0.12 TLSv1.2 280 New Session Ticket, Change Cipher Spec, Encrypted Handshake Message
代码/类型 :New Session Ticket, Change Cipher Spec, Encrypted Handshake Message
正在做什么 :服务器完成它的加密开启与确认动作:
New Session Ticket :下发一个加密的
Session Ticket 给客户端保存。下次你再连百度时,直接出示这个 Ticket
就能跳过繁琐的握手(实现快速恢复连接)。
Change Cipher Spec :服务器也通知你:“我也准备好了,后面我发给你的数据全都要加密了!”
Encrypted Handshake Message(Finished) :服务器发送加密的握手验证数据,双方至此TLS
握手彻底圆满结束 。
1 2 3 4 Transport Layer Security TLSv1.2 Record Layer: Handshake Protocol: New Session Ticket TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message
在 TLS
握手阶段,数据包内容是“前段完全明文,后段开始加密”的。一旦包里出现了
Change Cipher Spec
那个节点,从它后面的数据开始,就必须并且已经是加密的了。
阶段一:协商算法与传递随机数(1st RTT 开始)
Client Hello(客户端 → 服务端)
作用 :客户端发起加密连接请求。
携带内容 :
SNI(Server Name Indication) :告知要访问的域名(如
[www.baidu.com](https://www.baidu.com))。
客户端随机数(Client Random) :在本地生成的第 1
个随机数(明文传输)。
支持的加密套件列表(Cipher
Suites) :客户端支持的算法组合(如
ECDHE-RSA-AES128-GCM-SHA256)。
Server Hello & 凭证下发(服务端 → 客户端)
作用 :服务端确定方案、证明自己身份并下发密钥参数。
携带内容 :
Server
Hello :选定一套双方都支持的加密套件,并发送服务端生成的
第 2 个随机数(Server Random) (明文传输)。
Certificate :下发服务端的
数字证书(包含服务端公钥) ,供客户端校验身份。
Server Key Exchange :发送基于密钥交换算法(如
ECDHE)的服务端 临时公钥/参数 。
Server Hello
Done :告知客户端“我的第一轮汇报发完了”。
阶段二:密钥计算与开启加密(2nd RTT)
Client Key Exchange & 开启客户端加密(客户端 → 服务端)
作用 :客户端验证证书,发送自己的密钥参数,并通知开启加密。
过程与内容 :
验证证书 :客户端检查证书合法性(CA
签发、未过期、域名匹配等)。
Client Key Exchange :发送 ECDHE 算法的客户端
临时公钥/参数 。
本地计算主密钥 :此时,客户端根据
Client Random + Server Random +
ECDHE 算出的预主密钥 (Pre-Master Secret)**,在本地算出了最终用于数据加解密的
“主密钥(Master Secret / Session Key)”**。
Change Cipher
Spec :告知服务端“从下一字节开始,我发的所有数据都将用刚刚算出的主密钥加密!”
Encrypted Handshake Message
(Finished) :发送第一段用主密钥加密的校验数据,供服务端验证。
服务端确认与开启服务端加密(服务端 → 客户端)
作用 :服务端完成密钥计算,确认加密链路通畅,完成握手。
过程与内容 :
本地计算主密钥 :服务端根据收到的客户端 ECDHE
参数,结合之前存下的两个随机数,在本地算出了一模一样的主密钥 。
New Session Ticket (可选):下发加密的 Session
Ticket,方便下次连接时快速复用。
Change Cipher
Spec :告知客户端“我也准备好了,后面我发的数据也全部加密!”
Encrypted Handshake Message
(Finished) :发送加密的校验数据,供客户端校验。
阶段三:应用层数据传输(Application Data)
至此,TLS 握手彻底结束 。后续所有的应用层 HTTP
数据(如网页 HTML、API 请求)都会被主密钥加密 后塞入 TLS
记录(Record)中,通过底层的 TCP 管道安全传输。
重新传输
1 2 21 0.080248200 223.109.82.212 192.168.0.12 TCP 1060 [TCP Spurious Retransmission] 443 → 2993 [PSH, ACK] Seq=4201 Ack=1732 Win=82304 Len=1006 22 0.080493500 192.168.0.12 223.109.82.212 TCP 66 [TCP Dup ACK 18#1] 2993 → 443 [ACK] Seq=2605 Ack=5207 Win=263168 Len=0 SLE=4201 SRE=5207s
对面自动传输 4201-5207的数据给我。(认为这个数据包丢失)
我这边回复 5207 之前的数据都收到了,并没有缺失。
现实网络中,这两种机制是在同时协同运作的,并且各自扮演着不同的角色
在实际业务(如浏览网页、看视频、下载文件)中:
“发现缺了直接要”(快速重传 /
SACK)是处理丢包的主力军
原因 :因为网络一直在持续传输大量数据,后方的包会源源不断到达。一旦中间掉了一个包,客户端会立刻感知到(Seq
不连续)并连续回传 Duplicate ACK 催促。
优势 :触发非常极速(只要收到 3 个重复 ACK
就会触发),不需要死等几百毫秒的定时器 ,对网速和延迟影响极小。
“超时自动重发”(RTO 重传)是最后的保底防线
原因 :如果发生严重拥堵(比如后面的包全丢了,或者这是发送方发的最后一个包),客户端根本没有机会 收到后续数据包来触发“催促”信号。
作用 :此时只能靠发送方自己的 RTO
定时器硬等。定时器一响,不管三七二十一立刻重发。
代价 :RTO
超时通常会导致明显卡顿(因为通常要等数百毫秒以上),TCP
还会顺便把拥塞窗口(cwnd)剧烈缩小。
两种机制的对比
机制
触发主体
触发条件
适用场景
效率
快速重传 (Fast Retransmit)
接收方催促
接收方发现缺包,连续发 3 个 Duplicate ACK / SACK
持续传输中偶发丢包
极高 (毫秒级响应,不打断传输节奏)
超时重传 (RTO Retransmit)
发送方自动
发送方本地 RTO 定时器到期,仍未收到 ACK
严重拥塞 、尾包丢失 或 ACK
全丢
较低 (需死等超时,会降低传输速度)
回看你刚才的抓包案例(包 21)
抓到的包 21
属于第二种(超时重传) ,但它属于一种“误判导致的虚假重传”:
服务端的 RTO 定时器设得稍微太敏感了,或者网络延迟忽然抖动了一下(ACK
回传慢了)。
服务端没等到 ACK,定时器到期,于是自动重发了包 21。
结果你的电脑收到后一比对:“这包我早收到了呀!”于是回了个包 22(Dup
ACK)告诉对方:“收到了,进度已更新,别发了!”