目录
一、TCP概述
所属层级:传输层
核心角色:为应用进程提供端到端的可靠通信服务
关键特性:
面向连接(需先握手建立逻辑连接)
可靠传输(确保数据不丢失、不重复、有序)
基于字节流(无边界、有序的数据流)
二、TCP三大核心特性
面向连接、可靠传输、字节流
特性 | 说明 |
---|---|
面向连接 | 通信前需三次握手建立连接(逻辑链路) 仅支持一对一通信(不支持广播/组播) |
可靠传输 | 超时重传、确认应答(ACK) 流量控制(滑动窗口) 拥塞控制(慢启动、拥塞避免) |
字节流 | 数据无固定边界(如发送方写10次,接收方可读1次合并) 严格保序(先发先到) |
三、 对比UDP
(1)TCP、UDP对比
对比项 | TCP | UDP |
---|---|---|
连接方式 | 面向连接(需三次握手) | 无连接(直接发送数据) |
服务对象 | 一对一通信 | 支持一对一、一对多、多对多 |
可靠性 | 可靠传输(不丢、不重、有序) | 尽最大努力交付(不保证可靠性) |
拥塞/流量控制 | 有(滑动窗口、慢启动等) | 无(即使网络拥堵也不降速) |
首部开销 | 较长(20字节起,选项字段可扩展) | 固定8字节(极简) |
TCP像打电话:需先拨号(握手),通话中确保对方听清(可靠),挂断前需告别(四次挥手)。
UDP像发短信:直接发送,不保证对方是否收到。
(2)TCP、UDP头部格式:
TCP头部:
UDP头部:
(3)应用场景
TCP适用场景:
✅ 需要可靠传输的服务:
FTP
(文件传输)、HTTP/HTTPS
(网页浏览)、SMTP
(邮件发送)
UDP适用场景:
✅ 实时性或效率优先的服务:
DNS
(域名解析)、SNMP
(网络管理)、视频/音频流(如Zoom、直播)、广播/组播(如IPTV)
四、TCP的三次握手、四次挥手
(1)三次握手(建立连接)
目的:确保通信双方具备双向收发能力,同步初始序列号(ISN)
握手流程:
一SYN带SEQ,二SYN+ACK全都有,三ACK省字段!
三次交互后,双方均进入ESTABLISHED
状态,证明连接已可靠建立。
第一次握手(客户端主动出击)
客户端从CLOSE
进入SYN_SEND
状态、发送报文:SYN=1, SEQ=100
第二次握手(服务端双响应)
- 服务端从
LISTEN
进入SYN_RCVD
状态 - 回复报文:
SYN=1, ACK=1
:同意连接 + 确认收到客户端SYNSEQ=200
:服务端数据从200开始编号ACK_NUM=101
:期望下次收到客户端序号101的数据
- 服务端从
第三次握手(客户端最终确认)
注意:必须等待客户端最终确认(第三次握手),才能确保双向通信能力。
- 客户端发送:
ACK=1, ACK_NUM=201
(200+1)、第三次握手只需ACK确认 - 双方进入
ESTABLISHED
状态,连接正式建立
- 客户端发送:
面试常问:为什么不是2次、不是4次?
(1)两次握手的缺陷
- 历史重复连接:若客户端第一次发送的
SYN=100
因网络延迟未到达,超时重发SYN=101
并完成通信后关闭连接,旧的SYN=100
突然到达服务端,服务端会误认为新请求并建立无用连接,但客户端实际已关闭,导致服务端资源浪费(半开连接) - 单向连接风险:服务端无法确认客户端是否收到自己的SYN-ACK(客户端可能已崩溃),导致服务端资源浪费
(2) 四次握手的多余性
三次握手已能达成目的,第三次握手客户端发送ACK确认服务器的SYN+ACK,此时双向连接已确认双方都能正常收发数据,四次握手是多余的
- 无实际意义:TCP是全双工协议,第三次握手的
ACK=1;ACK_NUM=200+1
已完全确认双向连接。 - 效率降低:额外交互增加延迟,但未提升可靠性。
(2)四次挥手(断开连接)
关键字:
FIN=1
:终止连接标志(类似说“我要挂了”)
ACK=1
:确认标志(回应“知道了”)
1、为什么需要四次挥手?
TCP全双工特性:双方需独立关闭两个方向的连接:
- 第一次挥手:客户端→服务端方向关闭(发
FIN
) - 第二次挥手:服务端确认客户端的
FIN
(回ACK
) - 第三次挥手:服务端→客户端方向关闭(发
FIN
) - 第四次挥手:客户端确认服务端的
FIN
(回ACK
)
如果合并第二次和第三次挥手:服务端可能在发送ACK
后仍有数据要发送(如未传完的文件),需延迟发送FIN
。图中 CLOSE_WAIT
状态即为此设计(服务端处理剩余数据)。
2、为什么TIME_WAIT的等待时间是2MSL
关键词:
术语 | 含义 | 区别 |
---|---|---|
MSL | 报文最大生存时间,默认30秒(Linux) | 单位是时间(秒) |
TTL | 数据报可经过的最大路由跳数(Time To Live),每经过一个路由器减1,到0丢弃 | 单位是跳数(次) |
2MSL | TIME_WAIT状态的等待时长 = 2 × MSL | 确保旧报文完全消失 |
原因一:双向报文消亡
- 网络中可能残留发送方的数据包又要回应对方,一来一回最长需要2倍等待时间也就是
2×MSL
时间消亡。(TCP报文(含序列号、FIN/ACK标志)被封装在IP数据包中传输)
原因二:容错重传
若最后一个ACK丢失,被动关闭方会重发FIN:客户端在TIME_WAIT
期间收到重传的FIN,会重置2MSL计时器并重发ACK。
3、为什么需要TIME_WAIT状态
主动发起并关闭连接的一方才有TIME_WAIT状态
存在意义:
1、避免相同四元组(源IP/端口 + 目标IP/端口)的延迟报文干扰新连接。
2、保证被动关闭方能收到最终ACK,正常关闭连接。
五、TCP可靠传输性细解
1、流量控制
防止发送方数据发送速率超过接收方处理能力,避免:
- 接收方缓冲区溢出导致丢包
- 触发不必要的重传(浪费网络资源)
swnd:min(cwnd,rwnd)
swnd:发送窗口
cwnd:拥塞窗口(变化规则:网络中没有拥塞则cwnd变大,反之变小)
rwnd:接收窗口(接收方告知发送方当前可用的缓冲区空间(单位:字节)、动态调整)
如果一直无脑的发送数据给对方,但是对方处理不过来,就会导致触发重发机制,造成网络浪费
为了解决这种现象发生,TCP提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制。
TCP通过使用一个接收窗口(receive window)的变量来提供流量控制。接收窗口会给发送方一个指示到底还有多少可用的缓存空间。发送端会根据接收端的实际接受能力来控制发送的数据量。
接收端主机向发送端主机通知自己可以接收数据的大小,发送端会发送不超过这个限度的数据,这个大小限度就是窗口大小,(TCP的首部,有一个接收窗口,我们上面聊的时候说这个字段用于流量控制。它用于指示接收方能够/愿意接收的字节数量)
发送端主机会定期发送一个窗口探测包,这个包用于探测接收端主机是否还能够接受数据,当接收端的缓冲区一旦面临数据溢出的风险时,窗口大小的值也随之被设置为一个更小的值通知发送端,从而控制数据发送量。
2、拥塞控制
TCP的拥塞控制用于防止发送方的数据填满整个网络(而流量控制仅关注接收方缓存)。核心机制是拥塞窗口(cwnd),它是发送方动态调整的变量,根据网络拥塞程度变化:
- 窗口关系:发送窗口(swnd)取拥塞窗口(cwnd)和接收窗口(rwnd)的最小值(
swnd = min(cwnd, rwnd)
)。 - 调整规则:
- 无拥塞时增大
cwnd
; - 有拥塞时减少
cwnd
。
- 无拥塞时增大
- 拥塞判定:若发送方未按时收到ACK(触发超时重传),则认为网络拥塞。
TCP通过这种机制主动牺牲发送速率,避免网络陷入恶性循环(丢包→重传→更拥堵)。
TCP拥塞控制三种算法:
慢启动(探测带宽)→ 拥塞避免(线性保守)→ 快速恢复(快速调整)
(1)慢启动
慢启动是TCP拥塞控制的初始阶段,用于动态探测网络可用带宽。其核心规则如下:
- 初始窗口:建立连接时,拥塞窗口(
cwnd
)初始化为 1个MSS(最大报文段大小)。 - 指数增长:每收到一个ACK确认,
cwnd
增加1个MSS,导致窗口大小按轮次指数级增长(1→2→4→8…)。 - 发送速率:初始发送速率约为
MSS/RTT
(例如:MSS=1000字节,RTT=200ms,则初始速率为40kb/s)。
ssthresh(慢启动阈值)
当cwnd<ssthresh时;使用慢启动算法;
当cwnd>ssthresh时;停止使用慢启动算法,使用拥塞避免算法;
当cwnd=ssthresh时;既可以使用慢启动算法,又可以使用拥塞避免算法;
(2) 拥塞避免
- 触发条件:
cwnd ≥ ssthresh
。 - 增长规则:每经过一个RTT(往返时间),
cwnd
线性增加1个MSS(而非指数增长)。 - 目的:减缓窗口增长速率,避免网络过载。
- 拥塞响应:若发生超时重传,则:
- 将
ssthresh
设为当前cwnd
的一半; - 重置
cwnd = 1
,重新进入慢启动。
- 将
(3)快速启动
- 触发条件:收到 3个重复ACK(表明部分数据包丢失,但网络仍可传输)。
- 核心操作:
- 乘法减小:将
ssthresh
降为cwnd/2
; - 加法增大:
cwnd = ssthresh + 3 MSS
(因3个重复ACK表明3个数据包已到达); - 进入拥塞避免:此后每收到一个重复ACK,
cwnd
增加1 MSS;若收到新ACK,则退出快速恢复,进入拥塞避免。
- 乘法减小:将
- 目的:快速调整窗口大小,减少因丢包导致的性能骤降。
3、重传机制
(1)超时重传
超过指定时间没有收到对方的ACK应答报文,重新发送该数据
1、数据包丢失
2、确认应答丢失
每次超时重传的的时候,下次的超时时间会设置到原来的两倍。两次超时就说明网络差,别发了
(2)快速重传
收到3个重复ACK(表明后续数据包已到达,但中间某个报文段丢失),就会立即重传丢失的报文段,不以时间为驱动,以数据为驱动重传
工作流程:
- 发送方发出Seq1-5数据包
- Seq2丢失,接收方收到Seq3/4/5后仍返回Ack=2
- 发送方收到3个重复Ack=2后立即重传Seq2
- 接收方收齐数据后返回Ack=6
SACK(选择性确认):在TCP头部选项字段添加SACK信息,接收方通过SACK告知已收到的数据段,发送方精确重传确实丢失的数据段
Duplicate SACK:使用SACK告诉发送方哪些数据被重复接收了