TCP(滑动窗口/拥塞窗口补充)

目录

[一 滑动窗口](#一 滑动窗口)

[1. Zero Window](#1. Zero Window)

[2. Silly Window Syndrome](#2. Silly Window Syndrome)

[二 SACK/DSACK](#二 SACK/DSACK)

[1. SACK](#1. SACK)

[2. DRACK](#2. DRACK)

[三 拥塞控制](#三 拥塞控制)

[1. Congestion Avoidance](#1. Congestion Avoidance)

[2. TCP New Reno](#2. TCP New Reno)


一 滑动窗口

1. Zero Window

对端通告窗口大小为 0 ,接收端就不能在发送数据。

发送方会尝试探测对端窗口大小,即发送 ZWP (Zero Window Probe)报文,对端回复窗口大小,如果发多次 ZWP 得不到响应或者一直通告窗口为 0 则会关闭连接或者触发 RST 连接重置。

2. Silly Window Syndrome

对端通告窗口大小为 1,2,3.... 这种很小的窗口,发送端就只能发送很小的数据,但基于网络协议栈进行封包,TCP/IP最少报头都是 20 + 20,不携带选项,在携带这么少的数据,也就是 MSS,开销比较大。

  1. 接收端引起

可以采用 David D Clark's 方案,如果接收的数据之后的窗口小于某个阈值,则直接通告窗口大小为 0 ,后续接收端处理数据腾出的空间大于 MSS,或者 接收缓冲区一半已经空闲,或者达到某个阈值,才会重新通告发送端窗口值。

  1. 发送端引起

可以采用 Nagle's algorithm 方案,如果对端已经收到所有的报文或者刚连接什么也没发,也就是发送的报文全部都 ACK 了,则无论多大的包都直接发送,否则如果还有的报文没有 ACK,后续写的数据会积攒起来,如果积攒超过 MSS 则会打包发过去,或者前面发的所有包都 ACK 了也会直接发出去。

二 SACK/DSACK

1. SACK

  1. 触发超时重传,中间丢了多个包的,具体是重发一个还是都发?所以引入了 SACK。

SACK:需要双方握手的时候携带选项进行协商。

  • SACK 会记录已收到的非连续的报文序号,这样对端就能通过 ACK 和 SACK 得到哪些包丢了,比如:发 1000 2000 3000 4000 5000 6000,2000 3000 丢了,收到 1000,4-5-6000,ACK 3 次 2001,触发超时重传。
  • SACK:4 - 6000 收到了
  • ACK: 2001 之前的收到了
  • 发送端根据 ACK 和 SACK 把 2000-3000 重发。

缺点:

上述的 SACK 的数据包只是辅助重传哪些包,但不是真正的 ACK,可能因为某些原因,比如内存不足,接收缓冲区严重不足,回应 RACK 的时候把 RACK 的这些包丢弃了,因为不是正真确定的 ACK 的包。

2. DRACK

  • RACK 的一个子集,如果 RACK 的第一个字段被 ACK 覆盖 或者 第一个字段被 RACK 的第二个字段覆盖,那这个 RACK 就是 DRACK ,作用通知接收端哪些数据重发了

比如:

  1. ACK丢包:发送 1,2,3。 1,2 的 ACK 丢了,触发超时重传,重传 1,但回复的是 ACK 3(3之前的收到了),DRACK 1(重复收到1) 。

  2. 网络延迟:发送 1,2,3,4,5。 2 因为延迟,导致3,4,5先收到触发超时重传,重传 2,后续回复 ACK 5,DRACK 为空。延时的到了 ACK 5,DRACK 2。

所以 DRACK 可以有效的表示:

  • 发出的包丢了还是 ACK 的包丢了,ACK 丢了见上文,发出的包丢了根据后续报文回复的 ACK 即可。
  • 因为自己 超时重传 时间短导致重复发送报文,比如发 1,ACK 还没到或者丢了就 重传了,接收端就会再次 ACK 1,SACK 1。
  • 包乱序问题,先发的后收到,见上文。

SACK 和 DRACK 的值:SACK 的值会大于 ACK,RSACK 的值会小于 ACK。

三 拥塞控制

1. Congestion Avoidance

当拥塞窗口超过 ssthresh(慢启动阈值),则会进入 Congestion Avoidance(拥塞避免),后续拥塞窗口大小呈线性增加。

  1. 如果触发超时重传

最坏的情况:

  • ssthresh = 当前窗口大小 / 2
  • ssthresh = 1

随后继续进行慢启动。

  1. 如果触发快速重传

  2. TCP Tahoe 的实现和超时重传一样。

  3. TCP Reno 则会:

  • 窗口大小 = 当前窗口大小 / 2
  • ssthresh = 窗口大小

进入快速恢复阶段:

  1. 因为是快速重传,收到连续的 3 个 ACK,表示有 3 个包收到了,窗口大小 = ssthresh + 3 * MSS。

  2. 重传 ACK 指定的包,如果还是收到 ACK 指定的包则 窗口大小 = 窗口大小 + 1* MSS,如果收到新的 ACK,则 窗口大小 = ssthresh,随后进入拥塞避免阶段。

2. TCP New Reno

  1. 上述快速重传如果中间丢了多个包,只会重传第一个包,后面的则会进行超时重传,执行超时重传的解决逻辑,可以通过前面的 SACK 来动态发送。

  2. 这里引入了 TCP New Reno,在 TCP Reno 的基础上引入了 Partial ACK ,他会记录接收到的包的序列号最大的那一个,每次发送端重传数据包的时候和 Partial ACK 进行比较,小于就代表还有丢的包没重传,直到超过 Partial ACK 表示所有的包已收到。

相关推荐
sweet丶8 小时前
iOS开发必备的HTTP网络基础概览
网络协议·ios
是娇娇公主~11 小时前
HTTPS【密钥交换+证书校验】流程讲解
网络·网络协议·面试·https·ssl
北京耐用通信14 小时前
告别“蜘蛛网”接线!耐达讯自动化PROFIBUS 三路集线器让气缸布线“一拖三”的神操作
人工智能·物联网·网络协议·自动化·信息与通信
小于晏14 小时前
基于Socket实现的主流网络协议汇总
网络·网络协议
阿华hhh15 小时前
Linux系统编程(网络udp)
linux·服务器·c语言·网络·网络协议·udp
HansenPole82515 小时前
元编程笔记
笔记·网络协议·rpc
星哥说事16 小时前
SSL/TLS 证书管理,文件与数据库加密技术
数据库·网络协议·ssl
不知道累,只知道类16 小时前
[故障复盘] 生产环境 HTTP 连接池耗尽导致的“服务假死”分析
网络·网络协议·http
自由生长202417 小时前
计算机网络-从CGI 到 Unix Domain Socket:理解 Web 服务背后的进程通信演进
网络协议
lkbhua莱克瓦2417 小时前
TCP通信练习4-上传文件名重复问题
java·网络·网络协议·tcp/ip·tcp