TCP协议知识点

TCP协议知识点

一、基础概念与设计哲学

  1. 协议定位与历史

    • RFC 793(1981年首次定义),后续多个RFC扩展

    • 传输层核心协议,位于IP层之上,应用层之下

    • 面向连接:通信前需建立逻辑连接

    • 可靠交付:无差错、不丢失、不重复、按序到达

    • 字节流服务:无消息边界,与应用层报文分段/重组相关

  2. 核心服务特性

    • 全双工通信:同一连接双向数据流

    • 流量控制:接收方控制发送速率

    • 拥塞控制:网络拥塞时调整发送速率

    • 多路复用/解复用:通过端口号区分不同应用

二、报文格式详解(20-60字节)

复制代码
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         源端口 (16位)         |       目的端口 (16位)        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       序列号 (32位)                          |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                     确认号 (32位)                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据偏移 | 保留 | 控制标志位 |           窗口大小            |
| (4位)    | (6位)| UAPRSF (6位)|           (16位)              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|        校验和 (16位)         |        紧急指针 (16位)        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                   选项和填充 (变长,0-40字节)                |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            数据                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

关键字段详解:

  • 序列号(Sequence Number):本报文段第一个字节的编号,初始值(ISN)随机生成

  • 确认号(Acknowledgment Number):期望收到的下一个字节序号,表示之前所有数据已接收

  • 数据偏移:头部长度,单位4字节,最小5(20字节),最大15(60字节)

  • 控制标志位(6位)

    • URG:紧急指针有效(很少使用)

    • ACK:确认号有效(建立连接后所有报文必须设置)

    • PSH:推送功能,接收方应立即交付数据

    • RST:重置连接,异常终止

    • SYN:同步序列号,用于建立连接

    • FIN:结束连接,释放资源

  • 窗口大小:接收窗口大小,用于流量控制,最大65535字节(可通过窗口缩放扩展)

  • 紧急指针:URG=1时有效,指示紧急数据结束位置

三、连接管理完整状态机

1. 完整的三次握手过程
复制代码
客户端状态迁移:CLOSED → SYN_SENT → ESTABLISHED
服务器状态迁移:CLOSED → LISTEN → SYN_RCVD → ESTABLISHED

详细过程:
1. 客户端发送 SYN=1, seq=J
   客户端:CLOSED → SYN_SENT
   
2. 服务器响应 SYN=1, ACK=1, seq=K, ack=J+1
   服务器:LISTEN → SYN_RCVD
   
3. 客户端发送 ACK=1, seq=J+1, ack=K+1
   客户端:SYN_SENT → ESTABLISHED
   服务器:SYN_RCVD → ESTABLISHED
2. 完整的四次挥手过程(含所有中间状态)
复制代码
主动关闭方A,被动关闭方B:

1. A → FIN=1, seq=u → B
   A状态:ESTABLISHED → FIN_WAIT_1

2. B → ACK=1, seq=v, ack=u+1 → A
   B状态:ESTABLISHED → CLOSE_WAIT
   A状态:FIN_WAIT_1 → FIN_WAIT_2  (如果只有ACK)

3. B → FIN=1, ACK=1, seq=w, ack=u+1 → A
   B状态:CLOSE_WAIT → LAST_ACK

4. A → ACK=1, seq=u+1, ack=w+1 → B
   A状态:FIN_WAIT_2 → TIME_WAIT (等待2MSL)
   B状态:LAST_ACK → CLOSED
3. TCP状态机完整图谱
复制代码
                                 +---------+
                                 |  CLOSED |
                                 +---------+
                                    | ^
                       被动打开      | | 主动打开
                                    | |
                                    v |
      +---------+     SYN        +---------+
      |  LISTEN |<---------------| SYN_SENT|
      +---------+                +---------+
           |                         | ^
           | 接收SYN                 | | 发送SYN
           |                         | |
           v                         v |
      +---------+   SYN+ACK     +---------+
      |SYN_RCVD|<-------------->|ESTABLISHED|
      +---------+               +---------+
           |                         | ^
           | 关闭                    | | 关闭
           | 发送FIN                 | | 接收FIN
           v                         v |
      +---------+               +---------+
      |FIN_WAIT_1|              | CLOSE_WAIT|
      +---------+               +---------+
           |                         | ^
           | 接收ACK                 | | 关闭
           |                         | | 发送FIN
           v                         v |
      +---------+               +---------+
      |FIN_WAIT_2|              | LAST_ACK|
      +---------+               +---------+
           |                         | ^
           | 接收FIN                 | | 接收ACK
           | 发送ACK                 | |
           v                         v |
      +---------+               +---------+
      | TIME_WAIT|-------------->| CLOSED |
      +---------+   (2MSL超时)   +---------+
4. 特殊状态详解
  • FIN_WAIT_1:主动关闭方发送FIN后等待ACK

  • FIN_WAIT_2:收到对FIN的ACK,等待对方的FIN

  • CLOSING双方同时关闭的特殊状态

    复制代码
    A → FIN → B (A进入FIN_WAIT_1)
    B → FIN → A (B进入CLOSING)  // 几乎同时发送FIN
    A → ACK → B (A进入TIME_WAIT)
    B → ACK → A (B进入CLOSED)
  • CLOSE_WAIT:被动关闭方收到FIN,等待应用层关闭

  • LAST_ACK:被动关闭方发送FIN后等待ACK

  • TIME_WAIT

    • 持续时间:2MSL(Maximum Segment Lifetime,通常2分钟)

    • 作用1:确保最后的ACK能被重传

    • 作用2:让旧连接的报文在网络中消失,防止混淆

    • 问题:服务器大量TIME_WAIT影响性能

    • 解决方案:SO_REUSEADDR套接字选项

四、可靠性机制深度解析

1. 序列号与确认机制
  • 初始序列号(ISN)选择:基于时钟的随机算法,防止预测攻击

  • 累积确认:ACK=n表示已收到n-1及之前的所有字节

  • 选择性确认(SACK)

    • TCP选项字段,RFC 2018定义

    • 格式:Kind=5, Length, Left Edge, Right Edge

    • 允许接收方通知发送方非连续接收的数据块

    复制代码
    接收数据:1-1000, 1501-2000, 2501-3000
    SACK信息:[1501-2000], [2501-3000]
2. 超时重传机制
  • RTT测量

    • SRTT(平滑RTT):SRTT = α × SRTT + (1-α) × RTT_sample

    • RTTVAR(RTT变化):RTTVAR = β × RTTVAR + (1-β) × |SRTT - RTT_sample|

  • RTO计算:RTO = SRTT + 4 × RTTVAR

  • Karn算法:重传时不更新RTT估计(避免重传歧义)

  • 时间戳选项:精确测量RTT,即使重传也能准确测量

3. 快速重传与快速恢复
复制代码
触发条件:收到3个重复ACK(dup ACK)

过程:
1. 设置ssthresh = max(FlightSize/2, 2×MSS)
2. 重传丢失报文
3. 设置cwnd = ssthresh + 3×MSS(每个dup ACK表示一个报文离开网络)
4. 每收到一个额外dup ACK,cwnd增加1 MSS
5. 收到新数据的ACK,设置cwnd = ssthresh

五、流量控制:滑动窗口详解

1. 窗口结构
复制代码
发送方维护:
+---------------------------------------------------+
| 已发送已确认 | 已发送未确认 | 可发送 | 不允许发送 |
+---------------------------------------------------+
              ^              ^        ^
           LastByteAcked  LastByteSent   LastByteAcked + rwnd
           
接收方维护:
+---------------------------------------------------+
| 已接收已确认 | 可接收 | 不允许接收(窗口外)        |
+---------------------------------------------------+
              ^        ^
        NextByteExpected   NextByteExpected + rwnd
2. 零窗口问题与解决
  • 零窗口探测(ZWP)

    • 接收方窗口为0时,发送方发送1字节探测报文

    • 使用持久计时器(persist timer),指数退避重试

  • 糊涂窗口综合征(SWS)

    • 问题:发送小数据,接收方通告小窗口

    • 解决方案:

      • 接收方:窗口增大到MSS或缓冲区一半时才通告

      • 发送方:使用Nagle算法或等待足够数据

3. 窗口缩放选项(Window Scaling)
  • RFC 1323定义,用于长肥管道(LFN)

  • 选项格式:Kind=3, Length=3, Shift count

  • 实际窗口 = 通告窗口 × 2^(shift count)

  • 最大窗口可达1GB(理论值)

六、拥塞控制完整算法体系

1. 标准TCP Reno算法
复制代码
状态变量:
- cwnd: 拥塞窗口(报文段数)
- ssthresh: 慢启动阈值
- dupACKcount: 重复ACK计数器

四个核心阶段:
1. 慢启动(Slow Start): cwnd指数增长(每RTT翻倍)
   cwnd += MSS × (ACK确认的字节数/cwnd)
   
2. 拥塞避免(Congestion Avoidance): cwnd线性增长
   cwnd += MSS × (MSS/cwnd)  // 每RTT增加1 MSS
   
3. 快速重传(Fast Retransmit): 收到3个dup ACK
   
4. 快速恢复(Fast Recovery): 临时维护数据流
2. 主要变体算法对比
算法 发明时间 核心改进 适用场景
TCP Tahoe 1988 基本算法 已淘汰
TCP Reno 1990 快速恢复 标准实现
TCP NewReno 1999 改进快速恢复 多个丢包场景
TCP BBR 2016 基于瓶颈带宽和RTT 高带宽长延迟
TCP CUBIC 2008 三次函数增长 默认Linux算法
TCP Vegas 1994 基于延迟预测 研究用途
3. CUBIC算法详解(Linux默认)

text

复制代码
CUBIC使用函数:W(t) = C×(t-K)³ + W_max
其中:
- W_max: 丢包时的窗口大小
- K: 达到W_max所需时间,K = ³√(W_max×β/C)
- C: 缩放因子,默认0.4
- β: 乘性减小因子,默认0.7

特点:
- 在远离W_max时快速增长(凹函数)
- 接近W_max时缓慢增长(凸函数)
- 独立于RTT,公平性更好
4. BBR算法原理

text

复制代码
BBR v1/v2核心状态机:
- STARTUP: 指数增长寻找BDP(带宽×延迟积)
- DRAIN: 排空STARTUP创建的队列
- PROBE_BW: 周期性地探测(+25%, -25%, 维持)
- PROBE_RTT: 每10秒降低速率测量最小RTT

关键指标:
- BtlBw: 瓶颈带宽(最近10个RTT的最大交付率)
- RTprop: 往返传播延迟(最近10秒的最小RTT)
- BDP: BtlBw × RTprop(最优飞行数据量)

七、TCP选项全面解析

1. 选项格式与类型

text

复制代码
单个选项格式:
  Kind (1字节) | Length (1字节) | Data (变长)
  
重要选项:
1. MSS(Maximum Segment Size): Kind=2, Length=4
   - 声明本端能接收的最大报文段
   - 默认536字节(IPv4),1220字节(IPv6)

2. 窗口缩放(Window Scale): Kind=3, Length=3
   - 只在SYN报文中有效
   - shift值0-14,窗口最大1GB

3. SACK允许(SACK-Permitted): Kind=4, Length=2
   - 握手时协商,后续报文可用SACK选项

4. SACK信息(SACK): Kind=5, Length=变长
   - 每个SACK块8字节(左右边界各4字节)

5. 时间戳(Timestamps): Kind=8, Length=10
   - TSval: 发送时间戳
   - TSecr: 回显时间戳
   - 作用:精确RTT测量、PAWS防序号回绕

6. NOP(No-Operation): Kind=1
   - 选项对齐填充

7. EOL(End of Option List): Kind=0
   - 选项列表结束
2. 时间戳选项的PAWS机制

text

复制代码
序号回绕问题:32位序号在10Gbps链路上34秒回绕
PAWS(Protection Against Wrapped Sequences):
- 使用时间戳作为扩展序号
- 规则:如果TSval < 最近的有效时间戳,则丢弃报文
- 时间戳单调递增(即使系统时钟跳变)

八、高级特性与优化技术

1. 保活机制(Keepalive)

text

复制代码
参数(Linux默认值):
- tcp_keepalive_time = 7200秒(2小时)
- tcp_keepalive_intvl = 75秒
- tcp_keepalive_probes = 9次

工作流程:
1. 连接空闲2小时后,发送保活探测
2. 每75秒重试,最多9次
3. 总超时:2小时 + 75秒×9 ≈ 2小时11分
2. Nagle算法与Corking

text

复制代码
Nagle算法规则:
IF 有未确认数据
    THEN 缓存小数据直到收到ACK
ELSE
    立即发送

禁用:TCP_NODELAY选项

Linux扩展:TCP_CORK选项
- 类似Nagle,但由应用层控制
- 适合HTTP响应头+体的批量发送
3. 延迟确认(Delayed ACK)

text

复制代码
规则:
1. 每两个完整报文段确认一次
2. 最长延迟200ms(Linux默认40ms)
3. 有数据要发送时捎带确认
4. 广播/多播时不使用

优化:TCP_QUICKACK选项可禁用
4. 路径MTU发现(PMTUD)

text

复制代码
过程:
1. 设置DF(Don't Fragment)标志
2. 发送大报文
3. 收到ICMP "Fragmentation Needed"错误
4. 减小MSS,更新路由缓存

问题:ICMP被防火墙过滤导致黑洞
解决方案:PLPMTUD(Packetization Layer Path MTU Discovery)

九、缓冲区管理与性能调优

1. 缓冲区大小计算

text

复制代码
理论最优值:带宽延迟积(BDP)
BDP(字节)= 带宽(bps)× RTT(秒)/ 8

实际设置:
# Linux系统参数
net.ipv4.tcp_rmem = 4096 87380 6291456  # 最小 默认 最大
net.ipv4.tcp_wmem = 4096 16384 4194304
net.core.rmem_max = 6291456
net.core.wmem_max = 4194304

# 自动调整缓冲区(默认启用)
net.ipv4.tcp_moderate_rcvbuf = 1
2. 内存压力与公平性
  • 压力状态:系统内存不足时缩减缓冲区

  • 公平排队:相同RTT的流应获得相等带宽

  • RTT不公平性:标准TCP对长RTT连接不公平

十、异常处理与安全

1. 连接复位(RST)

text

复制代码
发送RST的场景:
1. 到不存在的端口的连接请求
2. 异常终止连接
3. 半开连接检测(收到已关闭连接的报文)
4. 收到无效序列号的报文

RST报文:不需要ACK确认
2. SYN Flood攻击防御

text

复制代码
攻击原理:伪造大量SYN不完成握手

防御机制:
1. SYN Cookie(Linux默认):
   - 编码MSS、序列号到SYN-ACK的序列号
   - 不分配连接资源直到收到ACK
   
2. SYN Cache:哈希表存储半开连接

3. SYN Proxy:代理完成握手后再与后端建立
3. 序列号随机化

text

复制代码
早期问题:可预测序列号导致连接劫持

解决方案(RFC 1948):
ISN = M + F(localhost, localport, remotehost, remoteport, secret)
其中M为单调递增计数器,F为哈希函数

十一、TCP扩展与替代协议

1. Multipath TCP(MPTCP)

text

复制代码
特性:
- 单个连接使用多个路径
- 向后兼容(对应用透明)
- 子流管理、调度、拥塞控制

应用场景:蜂窝/Wi-Fi切换、数据中心多路径
2. TCP Fast Open(TFO)

text

复制代码
目标:减少握手延迟
过程:
1. 首次连接获取TFO Cookie
2. 后续连接SYN携带数据和Cookie
3. 服务器验证Cookie,立即响应数据

限制:仅适用于幂等请求(如HTTP GET)
3. QUIC(基于UDP的替代)

text

复制代码
相比TCP优势:
- 0-RTT连接建立
- 改进的拥塞控制
- 无队头阻塞的多路复用
- 内置加密(TLS 1.3)
- 连接迁移支持

十二、性能监控与诊断

1. 关键性能指标(KPI)

text

复制代码
# 使用ss -it命令查看
1. 发送/接收窗口
2. RTT/RTTVAR
3. 拥塞窗口(cwnd)
4. 慢启动阈值(ssthresh)
5. 重传超时(rto)
6. 未确认字节数(unacked)
7. 丢失恢复状态(lost)
2. 网络诊断工具链

text

复制代码
1. 连接状态:netstat -ant, ss -s
2. 抓包分析:tcpdump, Wireshark
3. 流量监控:iftop, nethogs
4. 带宽测试:iperf3, netperf
5. 延迟分析:tcptraceroute, mtr
6. 缓冲区监控:ip -s link
3. Wireshark过滤与分析

text

复制代码
关键过滤器:
- tcp.analysis.flags:分析标志位
- tcp.analysis.retransmission:重传报文
- tcp.analysis.zero_window:零窗口事件
- tcp.analysis.window_update:窗口更新
- tcp.analysis.duplicate_ack:重复ACK

专家信息:
- 重复ACK编号
- 乱序报文
- 窗口冻结

十三、操作系统实现差异

1. Linux vs Windows TCP实现
特性 Linux Windows
默认拥塞控制 CUBIC CTCP(Vista+)
初始窗口 10 MSS 10 MSS(不同版本变化)
延迟ACK时间 40ms 200ms
TIME_WAIT回收 SO_REUSEADDR 快速回收选项
缓冲区自动调整 默认开启 需要手动优化
2. 内核参数调优示例

bash

复制代码
# Linux生产环境调优示例
# 缓冲区设置
echo "net.core.rmem_max = 134217728" >> /etc/sysctl.conf
echo "net.core.wmem_max = 134217728" >> /etc/sysctl.conf
echo "net.ipv4.tcp_rmem = 4096 87380 134217728" >> /etc/sysctl.conf
echo "net.ipv4.tcp_wmem = 4096 87380 134217728" >> /etc/sysctl.conf

# 拥塞控制
echo "net.ipv4.tcp_congestion_control = bbr" >> /etc/sysctl.conf

# 连接管理
echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf
echo "net.ipv4.tcp_fin_timeout = 30" >> /etc/sysctl.conf

# 启用TFO(TCP Fast Open)
echo "net.ipv4.tcp_fastopen = 3" >> /etc/sysctl.conf
相关推荐
jimy15 小时前
从Windows terminal里面的输出内容中截取trim IP 地址,再更新到.ssh/config文件里面
windows·tcp/ip·ssh
leo_2326 小时前
IP--SMP(软件制作平台)语言基础知识之六十四
服务器·开发语言·tcp/ip·企业信息化·smp(软件制作平台)·应用系统·eom(企业经营模型)
说私域6 小时前
技术赋能直播运营:开源AI智能名片商城小程序助力个人IP构建与高效运营
人工智能·tcp/ip·小程序·流量运营·私域运营
czhc11400756637 小时前
通信217
服务器·网络·tcp/ip
郝学胜-神的一滴8 小时前
深入理解TCP连接的优雅关闭:半关闭状态与四次挥手的艺术
linux·服务器·开发语言·网络·tcp/ip·程序人生
也许,也会1 天前
PLC1200 TCP/IP通信实操全解析:从基础到落地
服务器·网络·tcp/ip
Trouvaille ~1 天前
【Linux】网络层与IP协议详解:从地址到路由的完整指南
linux·运维·服务器·网络·tcp/ip·路由器·网络层
筵陌1 天前
Linux网络传输层协议TCP
linux·网络·tcp/ip
白太岁1 天前
通信:(2) TCP/UDP、流量/拥塞控制、ARP 与 Socket 应用
网络·c++·tcp/ip·udp