目录
1、概念
2、报文结构
3、核心特性
3.1 面向连接
3.2 可靠性:序列号和确认
3.3 流量控制
3.4 拥塞控制
3.5 全双工通信
3.6 应用层定义消息边界
4、连接管理
4.1 三次握手
4.2 四次挥手
5、应用场景
6、优缺点分析
1、概念
核心使命:在不可靠的IP网络之上,为应用层提供可靠的、面向连接的、基于字节流的传输服务
2、报文结构
一个 TCP 段由头部和数据部分组成:
-
源端口和目的端口: 标识发送和接收应用程序。
-
序列号: 本段数据中第一个字节在整个字节流中的编号。
-
确认号: 期望收到的下一个字节的序列号。隐含确认了该序列号之前的所有数据都已正确收到。
-
数据偏移: 指示 TCP 头部长度(以 4 字节为单位)。
-
保留: 未使用。
-
控制位 (Flags): 包含重要的控制信息:
-
URG
:紧急指针有效。 -
ACK
:确认号字段有效(建立连接后通常总是置 1)。 -
PSH
:提示接收方应立即将数据交付应用层(Push 功能)。 -
RST
:重置连接(通常表示严重错误)。 -
SYN
:同步序列号(用于建立连接)。 -
FIN
:发送方结束发送数据(用于关闭连接)。
-
-
窗口大小: 接收方通告的可用接收缓冲区空间(用于流量控制)。
-
校验和: 覆盖头部、数据和伪头部(IP 地址等)的校验值。
-
紧急指针: 当
URG=1
时有效,指向本段数据中紧急数据的最后一个字节的偏移量(较少使用)。 -
选项: 可变长,用于协商高级功能,如:
-
最大段大小: 通信双方协商一个
MSS(
Maximum Segment Size)
,限制发送的 TCP 段中数据部分的最大长度(通常基于 MTU 计算)。 -
窗口缩放因子: 允许通告超过 65535 字节的大窗口(用于高速网络)。
-
时间戳: 用于精确计算 RTT 和防止序列号回绕问题。
-
选择性确认: 允许接收方告知发送方收到了哪些非连续的数据块,提高重传效率。
-
-
数据: 应用层交付的数据(长度由 MSS 和窗口大小决定)。
3、核心特性
3.1 面向连接
作用:发送数据前确认双方可以通信,数据发送结束确认释放连接资源。
解决方案:在数据传输开始之前,通信双方(客户端和服务器)必须建立一条逻辑连接(TCP 连接),这个过程就是著名的三次握手。传输结束后,必须有序地释放连接,即四次挥手。
3.2 可靠性:序列号和确认
作用:确保发送的数据,另一端完整且正确的收到,没有收到需要重新发送。
TCP传输是分段的,一个HTTP响应报文会被操作系统切成多个MSS(Maximum Segment Size)大小的段,直到接收端接受到完整的报文为止。在此过程中,报文分段按照顺序进行发送,每个报文段在发送时,会做顺序编号,以便能够完整正确地组装。
解决方案:
-
序列号和确认应答: 每个发送的字节都被分配一个唯一的序列号。接收方收到数据后,必须发送一个确认应答,指明它期望收到的下一个字节的序列号(如果接收方发现中间段缺失,后续段以送达,会阻塞在缺失段,等待发送方重发--快速重传)。如果发送方在一定时间内没收到 ACK,它会重传未确认的数据。
-
校验和(正确性): 每个 TCP 段(Segment)都包含一个校验和字段。接收方计算校验和并与收到的值比较,如果不同,则丢弃该段(并可能触发重传)。
-
超时重传: 发送方为每个发出的段启动一个定时器。如果定时器超时前未收到该段的 ACK,则重传该段。
-
数据有序: 序列号保证了接收方能够将乱序到达的数据段按正确的顺序重新组装成应用层所需的字节流。
3.3 流量控制
作用:防止发送方发送数据过快,导致接收方缓冲区溢出而丢包。
该协议允许发送方在停止并等待确认前发送多个数据分组。由于发送方不必每发一个分组就停下来等待确认。因此该协议可以加速数据的传输,提高网络吞吐量。
解决方案:核心机制是滑动窗口协议。
-
接收方在 TCP 头部的
Window Size
字段中告知发送方自己当前接收缓冲区还有多少可用空间(即可接收的字节数)。 -
发送方维护一个发送窗口,其大小不能超过接收方通告的窗口大小。发送窗口内的数据允许被发送(无需等待 ACK)。随着接收方的确认和窗口更新,发送窗口向前“滑动”。
丢包的情况:已发送数据但是迟迟等不到Ack确认
解决方案:超时重发/重传
- RTO设长了,重发就慢,没有效率,性能差。
- RTO设短了,重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。
- 连接往返时间(RTT,Round Trip Time),指发送端从发送TCP包开始到接收它的立即响应所消耗的时间。
在 Unix 以及 Windows 系统中,最初其重发超时的默认值一般设置为6秒(重发时间必须是0.5秒的倍数)左右。数据被重发之后若还是收不到确认应答,则进行再次发送。此时,等待确认应答的时间将会以2倍、4倍的指数函数延长。此外,数据也不会被无限、反复地重发。达到一定重发次数之后,如果仍没有任何确认应答返回,就会判断为网络或对端主机发生了异常,强制关闭连接,并且通知应用通信异常强行终止。
3.4 拥塞控制
作用:防止发送方发送数据过快,导致网络核心(路由器)过载而引发大规模丢包和性能下降。
解决方案:TCP 通过感知网络是否拥塞(主要通过丢包作为主要信号,有时也利用延迟变化)来动态调整其发送速率(即调整 拥塞窗口)。拥塞窗口和接收窗口共同决定了发送方的实际可用窗口: Actual Window = min(Congestion Window, Receive Window)。
核心算法:
-
慢启动: 连接开始时或检测到拥塞后,拥塞窗口从一个很小的值(如 1 MSS)开始,每收到一个 ACK 就指数级增长(cwnd = cwnd + 1 个段)。
如果某个HTTP 事务有大量数据要发送, 是不能一次将所有分组都发送出去的。 必须发送一个分组, 等待确认; 然后可以发送两个分组, 每个分组都必须被确认,这样就可以发送四个分组了,以此类推。 这种方式被称为“ 打开拥塞窗口 ” 。
-
拥塞避免: 当拥塞窗口增长到慢启动阈值时,进入线性增长阶段(每 RTT cwnd 增加约 1 MSS),谨慎探测网络容量。
-
快速重传: 当发送方连续收到 3 个重复的 ACK(表明某个中间段丢失,但后续段已到达)时,不等超时立即重传丢失的段。
-
快速恢复: 在快速重传后,不是直接进入慢启动,而是将拥塞窗口减半(或做其他调整),然后进入拥塞避免阶段,更快地恢复传输速率。
3.5 全双工通信
一旦连接建立,数据可以在两个方向上同时独立传输。每个方向都有自己的序列号空间、接收缓冲区和滑动窗口。
其他通信方式的理解:
单工通信:数据只能在一个方向上流动,且是固定的。一方永远是发送方,另一方永远是接收方。
半双工通信:数据可以在两个方向上流动,但不能同时进行。通信双方可以轮流扮演发送方和接收方的角色,但在某一时刻只能做其中一件事。
3.6 应用层定义消息边界
TCP 对应用层交付的数据不保留任何边界信息。它把数据看作一连串无结构的字节流。
-
发送方 TCP 将应用层的字节流分割成合适大小的段发送(受限于 MSS)。
-
接收方 TCP 将接收到的字节按顺序放入接收缓冲区,应用层根据自己的协议从缓冲区中读取所需数量的字节。
这意味着应用层需要自己定义消息边界(如长度字段、分隔符)。
4、连接管理
4.1 三次握手
目的:同步双方的初始序列号,交换参数(如 MSS),建立连接。
过程:
-
SYN: 客户端发送一个 SYN 段(
SYN=1
),包含其初始序列号seq=x
。 -
SYN-ACK: 服务器收到 SYN 后,如果同意连接,则回复一个 SYN-ACK 段(
SYN=1, ACK=1
),包含自己的初始序列号seq=y
和对客户端 SYN 的确认ack=x+1
。 -
ACK: 客户端收到 SYN-ACK 后,发送一个 ACK 段(
ACK=1
),包含对服务器 SYN 的确认ack=y+1
。此时连接建立成功。
为什么不是两次握手:两次握手可能导致服务器在客户端不知情的情况下建立连接并等待数据,浪费资源。可能因网络延迟导致的过期连接请求报文被误认为是新连接请求。
为什么是三次握手:第三次握手,服务器需要确认客户端是否接收到自己的序列号(捎带确认),第三次握手是客户端是可以携带数据给服务端的。
为什么不是四次握手:最小化交互次数;服务端不能主动发起对客户端的访问。
4.2 四次挥手
目的:双方各自有序地关闭自己方向的数据传输通道,最终释放连接。
CLOSE-WAIT 状态就是为了保证服务端在关闭连接之前将待发送的数据处理完。
过程:
-
FIN: 主动关闭方(假设是客户端)发送 FIN 段(
FIN=1
),表示自己数据发送完毕。 -
ACK: 被动关闭方(服务器)收到 FIN 后,发送 ACK 确认(
ACK=1, ack=u+1
,u 是 FIN 的序列号)。此时客户端到服务器的数据传输通道关闭。 -
FIN: 当服务器也完成数据发送后,发送自己的 FIN 段(
FIN=1
)。 -
ACK: 客户端收到服务器的 FIN 后,发送 ACK 确认(
ACK=1, ack=w+1
,w 是服务器 FIN 的序列号)。服务器收到此 ACK 后,连接正式关闭。
为什么是四次挥手:因为 TCP 连接是全双工的,每个方向需要独立关闭。发送 FIN 表示“我这边没数据要发了”,ACK 是对这个声明的确认。需要双方都完成发送并发送 FIN,且对方的 FIN 都被确认后,连接才完全关闭。
TIME_WAIT 状态: 主动关闭方在发送完最后一个 ACK 后会进入 TIME_WAIT
状态,等待 2MSL。这有两个目的:
-
确保最后一个 ACK 能到达被动关闭方(如果丢失,被动方会重传 FIN,主动方在 TIME_WAIT 状态下还能响应)。
-
让网络中所有属于此连接的旧报文段都消失(过期),防止它们被后续新的、相同四元组的连接误收。
为什么是2MSL:
MSL 是 Maximum Segment Lifetime,报⽂最⼤⽣存时间,它是任何报⽂在⽹络上存在的最⻓时间,超过这个时间报⽂将被丢弃。
TIME_WAIT 等待 2 倍的 MSL,⽐较合理的解释是:⽹络中可能存在来⾃发送⽅的数据包,当这些发送⽅的数据包被接收⽅处理后⼜会向对⽅发送响应,所以⼀来⼀回需要等待 2 倍的时间。
⽐如如果被动关闭⽅没有收到断开连接的最后的 ACK 报⽂,就会触发超时重发 Fin 报⽂,另⼀⽅接收到 FIN 后,会重发 ACK 给被动关闭⽅, ⼀来⼀去正好 2 个 MSL。
补充:MSL(Maximum Segment Lifetime):TCP 报文段在网络中的最大存活时间,通常为 30 秒到 2 分钟
5、应用场景
-
Web 浏览: HTTP/HTTPS
-
文件传输: FTP, SFTP, SCP
-
电子邮件: SMTP, IMAP, POP3
-
远程登录: SSH, Telnet
-
数据库访问
-
企业级应用通信
6、优缺点分析
优点:
-
高可靠性(确保数据正确、完整、有序到达)。
-
自动流量控制和拥塞控制,适应网络状况。
-
连接管理清晰。
-
广泛支持,成熟稳定。
缺点:
-
开销大: 头部较长(至少 20 字节),连接管理(握手、挥手)带来额外开销和延迟。
-
速度相对慢: 确认、重传、拥塞控制机制引入了延迟,无法达到线路的绝对理论速度。在低延迟、可容忍少量丢包的应用中不如 UDP 高效。
-
队头阻塞: 如果一个 TCP 段丢失,后续即使已到达的段也不能立即交付给应用层,必须等待丢失段重传成功并按序重组。这在多路复用场景(如 HTTP/2)下可能成为瓶颈。