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 表示所有的包已收到。

相关推荐
游戏开发爱好者812 小时前
HTTPS 内容抓取实战 能抓到什么、怎么抓、不可解密时如何定位(面向开发与 iOS 真机排查)
android·网络协议·ios·小程序·https·uni-app·iphone
Fms_Sa16 小时前
UDP的一次双向通信
网络·网络协议·udp
keer_zu18 小时前
一个Modbus-TCP传感器数据传输方案
网络·网络协议·tcp/ip
代码哈士奇1 天前
使用仓颉开发一个简单的http服务
网络·网络协议·http·仓颉
云心雨禅1 天前
DNS工作原理:从域名到IP
运维·前端·网络协议·tcp/ip·github
それども1 天前
HTTP 三次握手最终状态变更的时机
网络·网络协议·http
2501_916008891 天前
HTTPS 下的 DDoS 防护与抓包分析实战,从检测到快速缓解的工程化打法
网络协议·ios·小程序·https·uni-app·iphone·ddos
想不明白的过度思考者1 天前
JavaEE初阶——HTTP/HTTPS 核心原理:从协议格式到加密传输
java·网络·网络协议·http·https·java-ee
一念&1 天前
每日一个网络知识点:应用层WWW与HTTP
网络·网络协议·http