网络原理相关内容(二)

一,数据传输过程中的文本结构

仅举xml与json为例

1)XML

java 复制代码
<bookstore>
  <book id="1">
    <title>XML入门指南</title>
    <author>张三</author>
    <price currency="CNY">59.90</price>
  </book>
  <book id="2">
    <title>JSON实战</title>
    <author>李四</author>
    <price currency="USD">39.99</price>
  </book>
</bookstore>
  1. 以<>为整体称为标签
  2. 有开始标签与结束标签(开始标签<>,结束标签</>)
  3. 开始标签和结束标签之间夹着的就是标签的值,标签可以嵌套(即标签之间可以夹着标签)
  4. 可以通过属性(如 id="1")为数据添加额外描述
  5. 标签可扩展,自定义标签
  6. 缺点是标签占据的资源甚至大于数据

2)JSON

java 复制代码
{
  "bookstore": {
    "book": [
      {
        "id": 1,
        "title": "XML入门指南",
        "author": "张三",
        "price": {
          "_currency": "CNY",
          "_value": 59.9
        }
      },
      {
        "id": 2,
        "title": "JSON实战",
        "author": "李四",
        "price": {
          "_currency": "USD",
          "_value": 39.99
        }
      }
    ]
  }
}
  1. 数据以 "键": 值 的形式组织,易于人阅读和编写,也易于机器解析和生成。
  2. 键和值之间使用 ":"分割
  3. 键值对之间使用 ","分割
  4. 把若干个键值对使用{}括起来,此时就形成了一个json对象
  5. 还可以把多个json对象放到一起
    使用 ","分隔开,并且使用[]整体括起来,就形成了一个json数组
  6. 相比XML更节约资源

3)protobuffer

比起XML与JSON都更加高效,但缺乏可读性,简单知晓即可

二,UDP协议

UDP协议具有无连接,不可靠性,面向数据报,全双工的特性

1)UDP报文的结构

  1. UDP数据报分为报头和载荷
  2. UDP报头中一共有4个字段,每个字段2个字节(一共8个字节)
  3. 2字节即16bit,因此端口号取值范围即0-65535(2的16次方-1)
  4. 因此一个UDP数据的最大长度也为65535bit约64KB
  5. 现如今由于数据日益增大64KB已不足以完整传输大多数据,但由于当前UDP协议,是集成在操作系统内核中的,不易于对UDP升级扩容(可简单理解为兼容性问题)
java 复制代码
 0                    15 16                    31
┌───────────────────────┬───────────────────────┐
│       源端口 (16)      │      目的端口 (16)     │
├───────────────────────┼───────────────────────┤
│      数据报长度 (16)    │      校验和 (16)       │
├───────────────────────┴───────────────────────┤
│                                               │
│                数据载荷(可变长度)              │
│                                               │
└───────────────────────────────────────────────┘

2)校验和相关内容

校验和的目的是检验数据是否发生错误

总原则:发送方和接收方遵循完全相同的步骤(根据持有数据进行计算),发送方计算并将结果(记为value1)存入"校验和"字段;接收方对收到的整个结构再次计算校验和(记为value2),如果二者数值相等证明数据大致无误,否则反之。

常用的校验和算法有CRC算法,md5算法,sha1算法...

1)md5算法的特点

  1. 定长,无论数据长短,计算出的md5数值都是固定长度
  2. 分散,计算md5过程中数据出现微小变化md5的值差距极大
  3. 不可逆,给出一个数据可算成md5值,但给出一个md5的值难以重新破解是何数据

因此md5也常用于密码学,例如网站存储的用户密码的md5值,网站如果被骇入也不会暴露用户的原密码

2)CRC算法的特点

  1. 只能检错,不能纠错
  2. 如果数据有两部分出现错误,可能导致两次CRC计算值相同

三,TCP协议

TCP报文具有有连接,可靠传输,面向字节流,全双工的特点

TCP报文段的结构比UDP复杂得多,也分为了报头与载荷,头部最小20字节

1)TCP报文结构

  1. 首部长度为4bit,但是每一个bit表示4bit
  2. 6个保留位中只有一个曾被短暂重新定义过(用于实验),其余始终保持为0。它就像一个战略储备,尚未被启用,为未来TCP功能拓展预留空间,避免不兼容问题
  3. 校验和与UDP类似,不赘述
  4. TCP由6个标志位,区分出了许多不同的报文
    一: 应答报文是TCP接收方发送给发送方的确认消息,用于告知发送方"我已经成功收到数据"(非应答报文为0,==但ACK=1的报文不一定都是纯粹的应答报文,它们可能同时具有其他功能,例如SYN+ACK三次握手的第二步,多个标志位可同时为1 ==)
    二:同步报文TCP结构中SYN位为1,用于TCP连接的建立的过程(三次握手)
    三:结束报文段:TCP结构中FIN位为1,用于TCP断开连接的过程,代码由close方法体现

java 复制代码
┌───────────────────────┬───────────────────────┐
│       源端口 (16)      │      目的端口 (16)     │ ← 与UDP相同的端口概念
├───────────────────────┼───────────────────────┤
│        序列号 (32)                            │ ← TCP可靠传输的核心
├───────────────────────┼───────────────────────┤
│        确认号 (32)                            │ ← 接收期望的下一个序号
├────┬────┬─────────────┼───────────────────────┤
│首部│保留│ 控制标志 (6) │      窗口大小 (16)    │ ← 流量控制关键字段
│长度│(6) │ U A P R S F │                       │
│(4) │    │ R C S S Y I │                       │
│    │    │ G K H T N N │                       │
├────┴────┴─────────────┼───────────────────────┤
│     校验和 (16)        │     紧急指针 (16)     │
├───────────────────────┴───────────────────────┤
│               选项和填充(可选,长度可变)       │ ← MSS、窗口缩放等
├───────────────────────────────────────────────┤
│                   数据载荷(可变长度)           │
└───────────────────────────────────────────────┘

2)可靠传输的实现

1)确认应答

确认应答是实现可靠传输的核心机制,依赖于序列号与确认序号实现

1.序列号

每个TCP数据是被分成多个TCP段发送的。每个TCP段的首部中有一个字段叫"序列号"

java 复制代码
应用层数据(字节流):
[字节0][字节1][字节2][字节3][字节4][字节5][字节6]...

TCP将其分段(假设每段3个字节):
段1: [字节0][字节1][字节2]  → 序列号 = 0
段2: [字节3][字节4][字节5]  → 序列号 = 3
段3: [字节6][字节7][字节8]  → 序列号 = 6
2.确认序号

确认序号是接收方告诉发送方下一个期望接收的字节序号,并且能表示确认序号前的数据都已经被接收

java 复制代码
场景:发送方发送3个段
段1: Seq=1000, Len=500  (字节1000-1499)
段2: Seq=1500, Len=500  (字节1500-1999)
段3: Seq=2000, Len=500  (字节2000-2499)

接收方处理:
收到段1 → 已成功接收字节1000-1499 → 确认序号=1500 (末尾1499+1)
收到段2 → 已成功接收字节1000-1999 → 确认序号=2000 (末尾1999+1)
收到段3 → 已成功接收字节1000-2499 → 确认序号=2500 (末尾2499+1)

2)超时重传

由于数据传输过程中涉及许多设备,可能会出现设备故障等一些列问题,造成数据的丢失。为了为确认应答多些保障,因此有了超时重传机制

超时重传是TCP可靠传输的核心机制之一,用于处理数据包丢失的情况。当发送方在预定时间内没有收到确认应答(ACK)时,会重新发送数据包

1.特点
  1. 重传次数是有上限的(重传次数达到一定数量都无法成功证明通路有误因此不再重传)
  2. 重传频率会越来越低(随着重传次数变多,丢包概率越来越低,因此重传频率降低节约资源)
2.注意事项

未收到ACK有两种情况

  1. 数据丢失未成功发送
  2. 数据成功发送,确认应答返回的ACK报文丢失

对于情况2如果发生重传数据可能出现重复接收因此,需要依靠数据序列号判定

java 复制代码
TCP socket 在内核中存在接收缓冲区(一块内存空间) 发送方发来的数据,是要先放到接收缓冲区中的
然后应用程序调用read/scanner.next才能读到数据

因此又分为两种情况
1)重复的数据还在缓冲区未被接收

此时,就拿着新收到的数据的序号,和缓冲区中的所有数据的序号对一下,查找是否有一致的,判定一致则去重丢弃数据

2)重复的数据已被应用数据读取
应用程序读取数据的时候,是按照序号的先后顺序,连续读取的,socket api 中可以记录上次读的最后一个字节的序号

如果重传而来的数据序列号小于等于已读序列号,可判定为重复,去重丢弃数据

3)TCP连接的建立(三次握手)

三次握手 是TCP连接建立的核心过程,其根本目的是同步双方的初始序列号,并确认双方的通信能力,为可靠的数据传输打下基础。(三次是建立可靠双向通信所需的最小次数,它在可靠性、安全性和效率之间取得了最佳平衡)

1.三次握手的具体过程

  1. 客户端发送SYN同步报文申请建立连接
  2. 服务器发送ACK应答报文表示收到请求的信息,并返回SYN同步报文表达可建立连接,这两步允许结合,令一个TCP的ACK与SYN同时为1
  3. 客户端发送ACK表示收到了服务器的ACK+SYN

注意! 理论上,服务器发送的SYN和ACK可以拆分成两个包。但这会增加一次额外的网络往返,降低连接建立的效率,而TCP设计者认为三次已经足够可靠地交换双方的初始序列号

2.三次握手的意义
  1. 三次握手可以确认通信路径是否畅通(三次握手都做不到,后续的数据交流肯定也有问题)
  2. 三次握手可以确认两端的发送能力与接受能力是否正常(三次握手的部分环节出问题可以推断是两端的哪部分功能出现问题)
  3. 三次握手的过程中也会协商一些必要的参数(所有关键的参数协商,都通过TCP报文头中的"可选项"字段在SYN和SYN-ACK报文中完成)

4)TCP连接的断开(四次挥手)

TCP 连接是全双工的,即数据可以在两个方向上独立传输。因此,关闭连接需要每个方向单独关闭。四次挥手就是双方互相确认、安全关闭这两个独立通道的过程(除了四次挥手正常关闭连接可能还存在一些异常断开连接的情况)

1.四次握手的具体过程

  1. 一端(以客户端为例)发送FIN结束报文申请建立连接
  2. 服务器发送ACK应答报文表示收到请求的信息
  3. 服务器再发送FIN结束报文表达接受断开连接
  4. 客户端等到ACK与FIN都接收后,发送ACK表示收到了服务器的的ACK与FIN

注意

  1. 区别于三次握手,四次挥手的二三步ACK与FIN通常无法合并(由于ACK的发送是由TCP协议栈内核自动触发的,而FIN的发送通常是由应用层代码显式控制的(三次握手的SYN也是由系统内核发送),这两者发生在不同的处理层次和时间点,因此在典型场景下无法合并)
  2. 因为即使一方发送FIN请求,另一方可能还有逻辑要处理因此无法把FIN封装在内核,一般应由代码主动实现发送,便于处理应完成的逻辑
2.服务器断开连接的部分情况
  1. 主动调用close断开
  2. 出现异常断开

注意,服务器为多个客户端提供服务,因此服务器的重要性极高,互联网厂商为了能正常提供服务,一般同一个功能的服务器都有冗余,用于系统的更新,应对异常等


5) TCP部分状态的认识

  1. LISTEN状态,服务器专用状态,表示 socket 正在监听端口,等待客户端连接
  2. ESTABLISHED状态,正常数据传输状态,
    客户端(主动打开方):在发送第三次握手的 ACK 后(接收了第二步,并完成第三步后)立即进入 ESTABLISHED
    服务器(被动打开方):在收到第三次握手的 ACK 后才进入 ESTABLISHED
  3. CLOSE-WAIT状态,被动关闭方(通常是服务器)在收到对端的 FIN 报文并回复 ACK 后,进入的一个等待状态(因为即使一方发送FIN请求,另一方可能还有逻辑要处理因此无法把FIN封装在内核,一般应由代码主动实现发送,== 该状态就是接收到FIN之后处理需完成逻辑到调用close前的状态==)
  4. TIME-WAIT状态(又称 2MSL 等待状态)是 TCP 连接终止过程中,主动关闭方在发出最终 ACK 后必须进入的一个等待状态,持续时间为 2MSL(MSL是一个系统内核的配置项,表示客户端到服务器之间,消耗的最长时间),TIME-WAIT状态存在的意义是,避免最后一个ACK发出时需要重传缺由于主动关闭方已经断开连接无法发送最后一步的ACK,无具体数值取决于实际需求与情况

6)滑动窗口

可靠传输实则付出了代价,传输效率将低于不可靠传输

在数据发送过程中,每个数据段都得等上个数据段得到ACK后才能发送下个数据段,数据段很多时等待ACK的时间可能多于数据发送的时间,因此效率是极低的

因此滑动窗口的出现即解决了上述问题

原本等待ACK的时间允许发送数据了(边发边收),虽然依旧要等待相同数量的ACK,但等待ACK的时间有数据发送,因此增加了效率

java 复制代码
初始窗口大小 = 4
发送方:窗口[1,2,3,4]
发送方缓冲区:
┌───┬───┬───┬───┬───┬───┬───┐
│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │  ← 数据序号
├───┼───┼───┼───┼───┼───┼───┤
│   │   │   │   │   │   │   │
└───┴───┴───┴───┴───┴───┴───┘
  ↑           ↑
左边界      右边界

发送方发送数据1-4:
┌───┬───┬───┬───┬───┬───┬───┐
│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
├───┼───┼───┼───┼───┼───┼───┤
│ ✓ │ ✓ │ ✓ │ ✓ │   │   │   │  ← ✓表示已发送
└───┴───┴───┴───┴───┴───┴───┘
  ↑           ↑
左边界      右边界

每收到一个左边界+1
┌───┬───┬───┬───┬───┬───┬───┐
│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
├───┼───┼───┼───┼───┼───┼───┤
│ ✓ │ ✓ │ ✓ │ ✓ │   │   │   │
└───┴───┴───┴───┴───┴───┴───┘
     ↑        ↑
   左边界    右边界
窗口向左滑动1位,数据1已确认

窗口滑动(即右边界+1),可发送数据5:
┌───┬───┬───┬───┬───┬───┬───┐
│ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │
├───┼───┼───┼───┼───┼───┼───┤
│   │ ✓ │ ✓ │ ✓ │ ✓ │   │   │  ← 发送数据5
└───┴───┴───┴───┴───┴───┴───┘
     ↑           ↑
   左边界       右边界

7)快速重传

在滑动窗口的过程中,如果其中某条数据丢失,将会触发快速重传

快速重传即当发送方连续收到3个重复ACK时,立即重传疑似丢失的数据包,而不必等待超时计时器到期

java 复制代码
时间   发送方                 接收方                网络状况
-------------------------------------------------------------------
t0   发送1-1000      →      接收1-1000          ✓ 成功
t1   收到ACK=1001    ←      发送ACK=1001        ✓ 正常
t2   发送1001-2000   →      丢失!              ✗ 丢包!
t3   发送2001-3000   →      接收2001-3000       ✓ 成功但乱序
t4   收到ACK=1001    ←      发送ACK=1001        ↑ 重复ACK#1
t5   发送3001-4000   →      接收3001-4000       ✓ 成功但乱序
t6   收到ACK=1001    ←      发送ACK=1001        ↑ 重复ACK#2
t7   发送4001-5000   →      接收4001-5000       ✓ 成功但乱序
t8   收到ACK=1001    ←      发送ACK=1001        ↑ 重复ACK#3
t9   ⚡检测到3个重复ACK → 立即重传1001-2000      ⚡触发快速重传
t10  收到重传的1001-2000 ← 发送ACK=5001         ✓ 累积确认

当序列号1001-2000的数据段丢失时:

  1. 发送方继续发送后续数据段(2001-3000、3001-4000、4001-5000等)
  2. 接收方收到这些乱序数据(乱序指的是缺失1001),将它们暂存于缓冲区
  3. 由于期待的数据(1001-2000)未到,接收方每次收到乱序数据都发送ACK=1001
  4. 发送方收到3个重复ACK=1001后,触发快速重传机制,重传1001-2000
  5. 接收方收到重传的1001-2000后:
    a) 将1001-2000交付给应用层
    b) 检查缓冲区,发现2001-3000、3001-4000、4001-5000都已缓存
    c) 这些数据现在变得连续(1001-5000)
    d) 发送累积确认ACK=5001(表示1001-5000全部收到)

注意接收方确实知道收到了哪些具体数据

接收到的数据包:

  1. 2001-3000 (序列号=2001)
  2. 3001-4000 (序列号=3001)
  3. 4001-5000 (序列号=4001)

发送的ACK:

ACK=1001, ACK=1001, ACK=1001 (三次重复)

但接收方内部知道:

缓存区中有:2001-3000, 3001-4000, 4001-5000(并且接收方知道缓存区中数据段各自的序列号,但在接收完丢包数据后仅返回最后一个数据段的序列号+1,这个序列号称为累计确认序号)

期待的是:1001-2000

累计确认是TCP协议中一种高效的确认机制:接收方发送的确认号(ACK)表示"该序号之前的所有数据都已正确接收"

java 复制代码
初始状态:
┌─────────────────┐
│ 期待:1001       │
│ 缓冲区:空       │
└─────────────────┘

收到2001-3000(乱序):
┌─────────────────┐
│ 期待:1001       │ ← 仍要1001
│ 缓冲区:2001-3000│ ← 缓存但不确认
└─────────────────┘
发送:ACK=1001

收到3001-4000(乱序):
┌─────────────────┐
│ 期待:1001       │ ← 仍要1001
│ 缓冲区:2001-4000│ ← 缓存更多
└─────────────────┘
发送:ACK=1001

收到4001-5000(乱序):
┌─────────────────┐
│ 期待:1001       │ ← 仍要1001
│ 缓冲区:2001-5000│ ← 缓存更多
└─────────────────┘
发送:ACK=1001

收到重传的1001-2000:
┌─────────────────┐
│ 交付:1001-2000  │
│ 交付:2001-3000  │ ← 可顺序交付
│ 交付:3001-4000  │ ← 可顺序交付
│ 期待:5001      │ ← 新的期待值
└─────────────────┘
发送:ACK=5001

8)流量控制

通过滑动窗口,数据传输效率得以提升,并且窗口越大传输效率越高,但是窗口又无法无限大,如果窗口过大接收方的处理速gon度跟不上发送方发送的熟读,缓冲区将占满,后续数据无法置于缓冲区发生丢(即使重传依旧无法避免)

为解决上述问题便有了流量控制

TCP结构中有16位窗口大小,这个字段仅在ACK报文中有意义,能反应窗口大小的合适值,而实际上的接收窗口大小为16位窗口大小的值*2的窗口拓展因子次方,窗口拓展因子是TCP报头选项部分的一个参数.

流量控制的核心即根据接收方的处理能力(缓冲区剩余空间大小)调整接受窗口大小,当接收窗口大小为0时数据应该停止发送

数据停止发送后发送方将发送窗口探测包,探测窗口大小,当窗口不为0时重新恢复发送

接收窗口与实际窗口关系见下文结合拥塞窗口


9)拥塞控制

数据从发送方传输至接收方,中间路径错综复杂,有的路径可能通畅有的路径可能拥堵,但最终传输速度由较拥堵的情况决定(短板效应),可以将中间路径统一为一个整体简化问题,发送方的数据发送过多可能造成网络崩溃,发送的数据过少又浪费网络带宽(理解为一个资源即可)

为解决上述问题便有了拥塞控制

发送方通过主动探测网络的传输能力,动态调整自己的发送速率,在充分利用带宽和避免造成网络崩溃之间取得最佳平衡

拥塞控制的动态调整过程

一般分为四个阶段

1.慢启动

我们先了解拥塞窗口,拥塞窗口是拥塞控制的一个动态阈值,体现了拥塞控制中一次能传输的数据多少,并且与接受窗口共同决定了实际有效的滑动窗口大小

  1. 慢启动阶段拥塞窗口由一个较小值开始以指数增长,达到一个被设定好的阈值后停止
  2. 由于刚刚开始数据传输,无法知晓网络拥堵情况因此由一个较小值作为拥塞窗口初始值来增长
  3. 慢启动的结束发生在网络堵塞或者达到阈值两种情况
2.拥塞避免
  1. 由慢启动达到阈值后,拥塞窗口开始以更慢的线性方式增长,避免指数增长过快直接导致网络拥堵
  2. 拥塞避免结束在网络拥堵时
3.快速重传与快速恢复
  1. 由快速重传处理拥塞使数据能正常传输后有两种策略
  2. 一种已被废弃的旧版本策略,重新将拥塞窗口设为较小值,并重新确定阈值,循环慢启动与拥塞避免
  3. 先使用的另一种方案称为快速恢复,将新阈值设为当前拥塞窗口的一半,以新阈值开始拥塞窗口的增长,直接进入拥塞避免阶段
4. 超时重传
  1. 当拥塞十分严重时无法依赖于快速重传恢复网络,便进入了超时重传,
  2. 若成功恢复便开始重新慢启动

10)延时应答

当用户请求瞬间涌入,每个请求都要求立即处理并返回结果,会给数据库、磁盘、外部API等下游服务带来巨大压力,导致响应变慢甚至服务崩溃

为解决上述问题便有了延时应答

  1. 延时应答运用了累计确认(上文快速重传部分已提及)的方法,每若干个数据段返回一次ACK,减少了ACK传输的数量节省了资源开销,并且提高了传输效率
  2. 并且延时应答可能提高接收窗口的大小,提高传输效率,对于立即应答更有优势
  3. 延时应答时会有设置一个定时器,定时器到期时,证明延时时间已达到上线,无论节省资源开销提高传输效率的目的是否达到,都必须发送ACK,以保证传输的可靠性
对于接收窗口,有无延时应答的对比

对于应用层读取数据,应用层只能读取TCP缓冲区中已被确认的数据,并且数据不是一经确认就被读取

java 复制代码
前提条件:TCP缓冲区已有40KB数据已确认
TCP接收缓冲区(64KB):
├── 已确认数据(ACK=4001已发送):
│   ├── 已读取部分:0KB(已被应用层取走)
│   └── 未读取部分:40KB(应用层还没取)
├── 未确认数据:0KB
└── 空闲空间(rwnd):24KB


时间线对比:
立即ACK场景:
T=0ms:  数据到达接收缓冲区
T=0.1ms: TCP立即发送ACK=5001(包含当前窗口14KB)
T=20ms: 应用层第一次读取机会(此时ACK早已发送!)
T=20ms: 应用层读取15KB数据
→ 结果:ACK中的窗口14KB已经发送,无法反映读取后的29KB

延时应答场景:
T=0ms:  数据到达接收缓冲区
T=0ms:  启动40ms延迟定时器
T=20ms: 应用层第一次读取机会
T=20ms: 应用层读取15KB数据
T=40ms: 定时器到期,发送ACK(包含读取后的窗口29KB)
→ 结果:ACK中的窗口29KB反映了最新状态

由于拥塞控制,随着接收窗口变小,拥塞窗口也变小,一般情况不会再有太多数据发送,考虑极端情况仍有数据持续发送

java 复制代码
T0: 收到10KB数据
   - 缓冲区:40KB旧 + 10KB新 = 50KB使用,14KB空闲
   - 启动40ms延迟定时器

T1: 又收到14KB数据
   - 缓冲区:40KB旧 + 10KB新 + 14KB更新 = 64KB全满!
   - 窗口变为0(零窗口)

T20ms: 应用层读取15KB旧数据
   - 缓冲区:25KB旧 + 10KB新 + 14KB更新 = 49KB使用
   - 空闲:15KB

T40ms: 发送延迟ACK
   - ACK确认到64,000(因为收到了63,999)
   - 报告窗口:15KB

结果:窗口从0变成了15KB,仍然比立即ACK的14KB大1KB

11)捎带应答

捎带应答指在发送数据报文时,顺带携带对对方数据的确认(ACK),从而避免单独发送一个纯ACK包

避免单独发送纯ACK包又进一步提高了TCP的效率


12)总结

上述的确认应答,超时重传,连接管理,滑动窗口,流量控制,拥塞控制,延时应答,捎带应答机制都不是割裂的,他们相互联系相互作用,可同时存在,保证了TCP的可靠性并尽可能的提高了TCP的效率

简单列举部分联系

  1. 确认应答与超时重传互补
  2. 确认应答帮助滑动窗口向前移动
  3. 流量控制与拥塞控制处理的就是滑动窗口相关问题
  4. 流量控制决定的接收窗口与拥塞控制的拥塞窗口共同决定了实际发送窗口的大小
java 复制代码
实际发送窗口 = min(接收窗口(rwnd), 拥塞窗口(cwnd))
  1. 延时应答通过影响接收窗口大小优化流量控制
  2. 捎带应答和延时应答可相互配合,延时应答创造了更多捎带应答的条件2
相关推荐
独行soc2 小时前
2026年渗透测试面试题总结-25(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
盟接之桥3 小时前
制造业EDI数字化:连接全球供应链的桥梁
linux·运维·服务器·网络·人工智能·制造
键盘鼓手苏苏3 小时前
Flutter for OpenHarmony:debounce_throttle 防抖与节流的艺术(优化用户交互与网络请求) 深度解析与鸿蒙适配指南
网络·flutter·交互
XiaoHu02073 小时前
Linux网络编程(第四弹)
linux·网络·智能路由器
REDcker4 小时前
HTTP 协议发展详解:从 HTTP/1 到 HTTP/3
网络·网络协议·http
AC赳赳老秦4 小时前
2026 智能制造趋势:DeepSeek 助力“黑灯”工厂运营,实现生产流程自动化
网络·数据结构·算法·安全·web安全·prometheus·deepseek
小鸡食米4 小时前
Keepalived高可用
运维·服务器·网络
白太岁5 小时前
操作系统开发:(10) 线程创建与调度的底层原理:从硬件行为解释线程
c语言·网络·系统架构
czhc11400756636 小时前
通信217
服务器·网络·tcp/ip