1. 运输层功能

  • 进程间的逻辑通信:屏蔽了底层细节,使得应用进程可以像直接通信一样交换数据
  • 多路复用:通过端口号,将多个应用进程的数据通过同一个运输层协议传输到网络层
  • 多路分用:通过端口号,将从网络层接收到的数据分发到正确的应用进程
  • 差错检测:检测数据在传输过程中是否发生错误,从而确保传输的可靠性
  • 流量控制:确保发送方的发送速率与接收方的处理能力相匹配,从而避免数据丢失和网络拥塞

类比

  • 应用层报文 = 信件
  • 进程 = 家庭成员
  • 主机 = 家庭
  • 运输层协议 = 家庭代表
  • 网络层协议 = 邮政服务

理解

  • 有两个家庭A和B,家庭成员之间需要通过信件互相通信,家庭A指派成员a作为家庭代表,家庭B指派成员b作为家庭代表,负责收集全部家庭成员的信去发送,同时将接收到的信分发给各个家庭成员,信件则通过邮政服务实现家庭到家庭之间的传递
  • a和b都是在各自的家庭进行工作的,并没有参与邮政服务的工作,因此运输层协议只是工作在端系统中
  • 邮政服务提供的是家庭到家庭之间的信件传递,对应于主机间的逻辑通信;a和b提供的是A家庭成员和B家庭成员之间的信件传递,对应于进程间的逻辑通信

端到端原则:是计算机网络设计中的一种设计哲学,强调将网络的功能应该尽可能放在网络端点(发送端和接收端),而不是放在网络核心(路由器、交换机)

  • 简化网络设计:降低了网络设备的复杂性,提高了网络的可靠性和可维护性
  • 提高灵活性:应用程序可以根据自身需求在端点实现特定的功能
  • 增强可扩展性:新的应用和服务可以在不修改网络核心的情况下部署

实际上,发送端和接收端代表的就是应用层协议和运输层协议,路由器和交换机代表的就是网络层协议和链路层协议

2. 运输层寻址

端口号(port):用于标识主机上的特定应用进程,使得数据能够正确地分发到目标进程,是一个16位的整数,范围是0到65535

  • 知名端口:0到1023,分配给系统或知名服务使用,如http使用80
  • 注册端口:1024到49151,分配给用户或应用程序使用,如mysql使用3306
  • 动态端口:49152到65535,分配给客户端进程使用,通常用于短暂的通信

TCP 和 UDP 的端口号空间是分开的,同一个端口号可以同时用于 TCP 和 UDP,而不会冲突

套接字(socket):由IP地址和端口号组成,用于唯一标识网络中的一个通信端点,是用户层与运输层之间的接口,是从网络向进程传递数据和从进程向网络传递数据的通道

3. UDP

3.1 UDP 性质

  • 无连接的:发送方和接收方之间无须建立连接,发送方将数据报传递给网络层之后就不再关心
  • 不可靠的:不保证数据是否到达接收方,也不在乎数据是否出现差错
  • 最简单的:不提供拥塞控制和差错修复,不会拆分报文,只是给报文添加一个UDP首部就作为数据报提交给网络层
  • 无长度限制:UDP数据报的长度完全由发送方应用进程决定,UDP协议不会限制分组大小

数据报特指无连接的报文段
虽然UDP协议不会限制数据包大小,但是网络层中的IP协议会限制数据包大小

UDP 优势:适用于快速一次性传输少量数据,如 DNS

  • 低延迟:不会引入建立连接的时延,也不会消耗额外资源来维护连接
  • 轻量级:UDP仅有8字节首部

UDP劣势:缺乏拥塞机制,UDP 不会因为网络拥堵而减缓发送速率,因此会进一步造成网络拥堵,甚至挤垮TCP会话

如果 DNS 使用 TCP,那么每秒成万上亿个 DNS 请求都需要建立连接,会严重占用宽带
虽然 UDP 不可靠,但是可以依赖于应用层的可靠协议,如 DNS 请求一旦发现失败,则会反复尝试

3.2 UDP 首部

4个字段:每个字段2字节

  • 源端口号:标识发送进程
  • 目的端口号:标识接收进程
  • 长度:整个数据报长度,即首部+数据的字节数
  • 检验和:验证数据在传输过程中是否发生了错误

检验和流程

  1. 构造伪头部:将源 IP 地址、目标 IP 地址、协议字段和 UDP 长度组合成伪头部
  2. 拼接数据:将伪头部、UDP 头部和数据部分拼接在一起
  3. 计算检验和
    1. 将拼接后的数据按 16 位(2 字节)分组
    2. 对所有 16 位分组进行二进制回卷求和
    3. 将求和结果的二进制反码作为检验和
  4. 存储检验和:发送方将计算得到的检验和存储到 UDP 头部的检验和字段中
  5. 检查检验和:接收方在收到 UDP 数据报后,按照相同的步骤计算检验和,如果得到的检验和为 0,说明数据在传输过程中没有发生错误,否则发生错误直接丢弃该数据报

伪首部只是拿来计算检验和,并不会用于实际传输
只能检测出奇数个比特差错,而且无法进行差错定位和差错修复

4. 可靠数据传输原理

4.1 可靠数据传输协议

4.1.1 基本概念

可靠:没有数据损坏和数据丢失,并且数据按发送顺序进行交付

可靠信道是运输层给应用层提供的抽象服务,实际上是通过较低层的不可靠信道传输,经过运输层的处理后才变得可靠

基本函数

函数名调用者作用
rdt_send(data)应用层指示运输层发送方从应用层中获取数据
rdt_rcv(packet)网络层指示运输层接收方从网络层获取分组
make_pkt(data)运输层发送方将数据加上首部封装成分组
extract(packet, data)运输层接收方从分组中取出数据
udt_send(packet)运输层发送方将分组发送到网络层
deliver_data(data)运输层接收方将数据交付给应用层

有限状态机(Finite-State Machine,FSM):由状态、状态转移、事件和操作组成

  • 圆:状态
  • 箭头:状态转移,取决于事件和操作
  • 横线上方:引起状态转移的事件
  • 横线下方:实现状态转移的操作
  • Λ\Lambda:空,表示没有事件或没有操作

4.1.2 rdt1.0

rdt1.0:底层信道是完全可靠,不需要进行差错检测和修复

状态事件操作状态转移
发送端等待调用应用层调用封装分组并发送转移到自身
接收端等待调用网络层调用提取数据,交付应用层转移到自身

4.1.3 rdt2.x

4.1.4 rdt.2.0

自动重传协议(Automatic Repeat reQuest,ARQ)

  • 检测:发送方会将检测字段封装进分组中,接收方会根据检测字段进行差错检测
  • 反馈:肯定确认(positive acknowledgement,ACK)否定确认(negative acknowledgement,NCK),接收方需要向发送方发送ACK分组或NCK分组
  • 重传:接收方接收到NCK分组后,需要重传该分组

停等协议(stop-and-wait):发送方不会发送新分组,直到发送方收到来自接收方的肯定确认

rdt2.0:实现了差错检测,接收方通过ACK和NAK告知发送方分组情况

函数名调用者作用
isNAK(rcvpkt)和isACK(rcvpkt)运输层发送方判断发送的分组是否被正确接收
notcorrupt(rcvpkt)和corrupt(rcvpkt)运输层接收方判断接收的分组是否有差错

发送端

状态事件操作状态转移
等待调用应用层调用封装分组并发送转移到“等待确认”
等待确认接收ACK不执行任何操作转移到“等待调用”
等待确认接收NAK重传分组转移到自身

接收端

状态事件操作状态转移
等待调用分组没有差错提取数据,交付应用层,发送ACK转移到自身
等待调用分组出现差错发送NAK转移到自身

4.1.5 rdt.2.1

rdt2.0的局限性:没有考虑到ACK或NAK分组受损的可能性

不合适的处理方案

方案情况结果
发送方利用新分组询问接收方新分组也有可能差错无限循环确认
发送方可以修复差错需要增加足够的检验和比特首部过大
发送方重传分组可能在ACK的情况下依旧重传冗余分组

rdt2.1:让发送方对分组进行编号,将序号封装在首部字段,接收方仅需要根据序号就可以判断当前分组是否是冗余分组

函数名调用者作用
has_seq1(rcvpkt)和has_seq0(rcvpkt)运输层接收方确认当前分组的序号
notcorrupt(rcvpkt)和corrupt(rcvpkt)运输层接收方和运输层发送方判断接收的分组是否有差错

发送端

状态事件操作状态转移
0号等待调用应用层调用封装0号分组并发送转移到“0号等待确认”
0号等待确认接收NAK或者分组出现出错重传0号分组转移到自身
0号等待确认接收ACK并且分组没有出错不执行任何操作转移到“1号等待调用”
1号等待调用应用层调用封装1号分组并发送转移到“1号等待确认”
1号等待确认接收NAK或者分组出现出错重传1号分组转移到自身
1号等待确认接收ACK并且分组没有出错不执行任何操作转移到“0号等待调用”

接收端

状态事件操作状态转移
0号等待调用分组出现差错发送NAK转移到自身
0号等待调用分组没有差错但是收到1号分组发送ACK转移到自身
0号等待调用分组没有差错并且收到0号分组提取数据,交付应用层,发送ACK转移到“1号等待调用”
1号等待调用分组出现差错发送NAK转移到自身
1号等待调用分组没有差错但是收到0号分组发送ACK转移到自身
1号等待调用分组没有差错并且收到1号分组提取数据,交付应用层,发送ACK转移到“0号等待调用”

4.1.6 rdt2.2

rdt2.2:与rdt2.1的唯一差别在于ACK和NAK也封装了序号

4.1.7 rdt3.0

rdt2.x的局部性:如果分组丢失,那么发送方和接收方都无法做出响应来处理

rdt3.0:采用基于时间的重传机制

  • 重传:从发送方的观点来看,只要能处理好冗余分组,重传是一种万能的方案
  • 基于时间:依靠倒计时定时器(countdown timer)
    • 启动:每次发送一个分组都需要启动倒计时定时器
    • 中断:如果在指定时间量内没有得到肯定确认中断倒计时定时器,并重传分组
    • 重置:如果在指定时间量内得到肯定确认,重置倒计时定时器

发送端

状态事件操作状态转移
0号等待调用应用层调用封装0号分组并发送,启动定时器转移到“0号等待确认”
0号等待确认接收1号ACK或者分组出现出错不执行任何操作转移到自身
0号等待确认超时重传0号分组,启动定时器转移到自身
0号等待确认接收0号ACK并且分组没有出错中断计时器转移到“1号等待调用”
1号等待调用应用层调用封装1号分组并发送,启动定时器转移到“1号等待确认”
1号等待确认接收0号ACK或者分组出现出错不执行任何操作转移到自身
1号等待确认超时重传1号分组,启动定时器转移到自身
1号等待确认接收1号ACK并且分组没有出错中断计时器转移到“0号等待调用”

比特交替协议(alternating-bit):分组序号在0和1之间交替

rdt3.0/一对一确认/停等协议的局限性:吞吐量非常低!
假设可用吞吐量R=1Gbps,RTT=30ms,分组长L=8000bits,忽略ACK的发送时延
发送方相邻两个分组的发送间隔是RTT+L/R=30.008ms
实际吞吐量为8000bits/30.008ms≈267kbps
宽带利用率只有可怜的267kbps/1Gbps=0.0267%(这还是在分组没有任何差错,不考虑协议处理时间,路由器的排队时延的情况下)

4.2 流水线传输协议

4.2.1 流水线技术

流水线技术:允许发送方在一定限度内发送多个分组而无需等待每个分组来自接收方的ACK

  • 增加序号范围:跟踪多个分组,每个分组具有唯一序号
  • 滑动窗口机制:发送方需要缓存尚未确认的分组以便重传,接收方也需要缓存尚未排序分组以便按顺序交付

4.2.2 回退N步

回退N步协议(Go-Back-N, GBN):假设发送方有缓存,而接收方没有缓存

  • 窗口大小(N):发送方窗口所能容纳的最大分组数
  • 初始序号(startSeq):传输的第一个分组的序号
  • 发送方基序号(base):最小未确认分组的序号
  • 下一个序号(nextS e q):最小未发送分组的序号
  • 窗口长度(window size):发送缓冲区大小
  • 接收方期望序号(expectSeq):接收方期望收到分组的序号

注意如果超过了最大序号,需要进行取模运算

序号范围

  • [0,base-1]:已经发送且已经被确认的分组
  • [base,nextSeq-1]:已经发送但还没有被确认的分组
  • [nextSeq,base+N-1]:还没有发送但即将发送的分组
  • [base+N,…]:从未进入过发送方缓冲区的分组

GBN实现手段

  • 窗口判断:如果nextSeq == base + N,则窗口已满
  • 累积确认:接收方不会发送NAK只会发送ACK,表示已经成功接收到 [startSeq:expectSeq] 的所有分组
  • 超时记录:发送方使用一个定时器,用来记录 base 的等待时间
  • 失序丢弃:接收方会丢弃一个正确接收但失序的分组,而不会缓存它

失序丢弃的可解释性:接收方在期望接收到n的时候接收到了n+1,哪怕接收方缓存了n+1,但是发送方也不知情,因此发送方依旧会在传送n之后再次传送n+1。因此接收方缓存n+1就没有任何意义了

GBN流程

  • 发送方
    • 接收到错误ACK:丢弃
    • 接收到base的ACK:递增 base,重启定时器
    • 窗口未满:递增nextSeq并发送
    • 定时器超时:重启定时器,发送 base

  • 接收方
    • 接收到错误数据:丢弃
    • 接收到正确数据,且 seq != expectSeq + 1:发送 expectSeq 的 ACK
    • 接收到正确数据,且 seq == expectSeq + 1:递增 expectSeq 并发送 expectSeq 的 ACK

GBN协议的局限性:发送方必须从出错的分组开始重新发送所有后续分组,这可能导致大量无用数据的重传,特别是在高丢包率的网络中,带宽利用率会降低

4.2.3 选择重传

选择重传协议(Selective Repeat, SR):假设发送方和接收方都有缓存

  • 发送方需要标记发送窗口中哪些分组已经被确认
  • 接收方需要标记接收窗口中哪些分组已经被接受

发送方

  • 接收到 send_base 的 ACK,且窗口内存在分组还未被确认,send_base 更新为窗口中最近未被确认的分组序号,并重启计数器
  • 接收到 send_base 的 ACK,且窗口内全部分组都被确认,send_base = send_base + N,并重启计数器
  • 接收到 seq > send_base 的 ACK,如果 seq 在发送窗口内,标记窗口中该分组为已确认
  • 计数器超时,重传 send_base 分组,重启计数器

接收方

  • 接收到 recv_base 分组,且窗口内存在分组还未收到,recv_base 更新为窗口中最近未收到的分组序号
  • 接收到 recv_base 分组,且窗口内全部分组都收到,recv_base = recv_base + N
  • 接收到 seq > recv_base 分组,如果 seq 在接收窗口内,缓存该分组
  • 接收到 seq < recv_base 之前的分组,忽略该分组,并发送该分组的 ACK

窗口尺寸问题

  • 过小:可发送/可接收的分组太少了,导致带宽利用率低
  • 过大:缓存大量乱序分组或未确认分组,需要消耗更多内存
  • 序号重叠:窗口尺寸接近或超过序号空间的一半,可能会导致序号重复使用,从而导致接收方无法区分新旧分组,造成协议错乱

5. TCP

5.1 TCP 性质

  • 面向连接的:在发送数据之前,通信的两端需要建立一个逻辑连接
  • 面向字节的:TCP将数据看成字节流的形式
  • 全双工的:通信两端都可以接收和发送数据,且两个方向的数据传输可以同时进行,互不干扰
  • 点对点的:每一条连接只能连接两个端点,不存在第三方
  • 可靠的:保证传送的数据无差错、不丢失、不重复、有序
  • 有长度限制:根据接收方的缓存情况和网络拥塞情况来决定TCP报文段长度

5.2 TCP 首部

字段长度/bit作用
源端口号(Resource Port)16标识数据传输的起始端点
目的端口号(Destination Port)16标识数据传输的终止端点
序号(Sequence Number)32标识TCP数据流中的字节顺序
确认号(Acknowledgement Number)32标识下一个期望接收的字节序号
首部长度(Header Length)4指示TCP头部长度,以32位字为单位
保留区域(Reserved)4保留,可能会在未来的协议扩展中有新的用途
减少拥塞窗口(CWR)1发送方用于确认它已经响应了网络拥塞,调整了其拥塞窗口
显式拥塞通知(ECE)1接收方用于通知发送方网络发生了拥塞
标志(Flags)6控制位,标识特殊功能
接收窗口(Window)16指定接收方的缓存区域大小
检验和(Checksum)16检验报文段在传输过程中是否出错
紧急指针(Urgent Pointer)16指示紧急数据在数据流中的位置
选项(Options)可变用于传输协议的扩展功能
填充(Pad)可变因为选项可变,因此需要填充来确保首部长度是4B的整数倍
有效载荷(Payload)可变实际传输的数据

标志(按顺序)

  • URG(Urgent):指示报文段中包含紧急数据,接收方应优先处理
  • ACK(Acknowledgement):指示已成功接收数据
  • PSH(Push):指示接收方应尽快将数据交付到应用程序,而不是等待缓冲区满
  • RST(Reset):指示发送方强行终止TCP连接
  • SYN(Synchronize):指示发送方请求建立TCP连接
  • FIN(Finish):指示发送方请求断开TCP连接

序号和确认号

  • 序号:是当前主机发送报文段的首字节编号
  • 确认号:是当前主机期望接收到来自另一方的字节编号

5.3 连接控制

5.3.1 三次握手

三次握手流程

  1. 客户端向服务器发送SYN报文段,seq=client_isn,ack=0
  2. 服务器向客户端发送SYN-ACK报文段,seq=server_isn,ack=client_isn+1,为TCP连接分配缓存和变量
  3. 客户端向服务器发送ACK报文段,seq=client_isn+1,ack=server_isn+1,为TCP连接分配缓存和变量

SYN报文段和SYN-ACK报文段即使不带任何数据,也会消耗一个序号
client_isn和server_isn都是随机选择的

为什么需要三次握手?

  • 第一次握手表示客户端请求建立连接
  • 第二次握手表示服务器同意建立连接
  • 第三次握手表示连接已经成功建立

SYN洪泛攻击:攻击者只进行第一次握手,但不完成第三次握手,让服务器维持半开连接状态,从而耗尽服务器的资源,使其无法处理合法请求

5.3.2 四次挥手

四次握手流程

  1. 客户端向服务器发送FIN报文段,seq=x,ack=y
  2. 服务器向客户端发送ACK报文段,seq=y+1,ack=x+1
  3. 服务器继续发送还未发送的报文段(可能没有)
  4. 服务器向客户端发送FIN报文段,seq=z,ack=x+1
  5. 客户端向服务器发送ACK报文段,seq=x+1,ack=z+1
  • FIN报文段即使不带任何数据,也会消耗一个序号
  • x、y、z是先前传输的最后一个字节编号+1

TCP 客户的两个特殊阶段

  • FIN_WAIT_2阶段:客户端继续接收服务器可能还未传输完的数据,并等待来自服务器的 FIN 报文段
  • TIME_WAIT阶段:如果客户端返回的最后一个 ACK 丢失,服务器会重传 FIN 报文段,因此实际上客户端还需要等待 2个最长报文段存活时间(Maximum Segment Lifetime, MSL),才能确保 TCP 连接完全关闭

5.3.3 终止连接

终止连接流程

  1. 当一方检测到连接异常时,会发送一个 RST 报文段
  2. 接收方收到 RST 报文段后,会立即终止连接,不再进行任何数据传输

适用情况

  • 异常连接:服务器接收到一个无效的或不期望的报文段,例如客户端试图访问一个没有在服务器上监听的端口,或者在连接过程中发送了错误格式的报文段
  • 拒绝连接:服务器收到非法的连接请求,例如客户的连接请求未被授权,该端口不允许被访问,或需要额外的安全检查
  • 重置连接:一个已经建立的连接变得无效或异常,例如由于网络故障或应用程序错误,连接需要被强制关闭

5.4 差错控制

5.4.1 累计确认

  1. 发送方发送seq=92的分组
  2. 接收方成功接收到了seq=92的分组,由于分组长为8,因此返回ack=100
  3. 发送方发送seq=100的分组
  4. 接收方成功接收到了seq=100的分组,由于分组长为20,因此返回ack=120
  5. 发送方虽然没有收到ack=100,但是在seq=92的超时间隔内,收到了ack=120,因此发送方可以确定接收方已经接收到了120之前的所有数据,否则ack不可能是120

实际上,传统TCP没有使用选择重传机制,而是在GBN协议上进行拓展

5.4.2 动态调整超时间隔

采样往返时间(SampleRTT):从发送一个 TCP 报文段到收到其 ACK 所花费的实际时间

SampleRTT=tacktsendSampleRTT=t_{ack} − t_{send}

均值往返时间(EstimatedRTT):对采样 RTT 进行平滑处理后的估计值,用于反映网络的长期 RTT 趋势,其中α\alpha是平滑因子,通常取 0.125

EstimatedRTT=(1α)EstimatedRTT+αSampleRTTEstimatedRTT = (1-\alpha) \cdot EstimatedRTT + \alpha \cdot SampleRTT

偏差往返时间(DevRTT):是采样 RTT 与均值 RTT 的偏差,用于衡量 RTT 的波动情况,其中β\beta是平滑因子,通常取 0.25

DevRTT=(1β)DevRTT+βSampleRTTEstimatedRTTDevRTT = (1-\beta) \cdot DevRTT + \beta \cdot |SampleRTT-EstimatedRTT|

超时重传时间(Retransmission Time-Out, RTO):指示了发送方在未收到确认时理应等待重传的时间长度,如果太小致不必要的重传,如果太大导致时延变大

RTO=EstimatedRTT+4DevRTTRTO = EstimatedRTT + 4 \cdot DevRTT

5.4.3 快速重传

TCP接收方的行为

  • 接收到顺序报文段:发送累计ACK
  • 接收到出错报文段:发送冗余ACK
  • 接收到乱序报文段:发送冗余ACK
  • 接收到重复报文段:发送冗余ACK
  • 短时间内接收到大量顺序报文段:延迟发送累积ACK

快速重传:可以发现,上述三种异常情况都是发送冗余ACK,因此如果TCP发送方接收到3个冗余ACK,则可以认为该ACK所期望的报文段已经丢失,发送方就会立即重传该报文段,而不会等待超时

5.5 流量控制

意义:防止发送方发送数据过快,导致接收方缓冲区溢出

发送方维护一个接收窗口(rwnd)

  • 接收方:通过 TCP 头部的窗口字段来通告其当前可用的缓冲区大小
  • 发送方:根据接收方的窗口大小动态调整发送的数据量

零窗口

  1. 如果接收方的缓冲区已满,接收方会发送一个窗口字段为 0 的 ACK 报文段,通知发送方暂停发送数据
  2. 当发送方收到零窗口通知后,会定期发送窗口探测报文段,询问接收方的窗口状态,从而重启发送

5.6 拥塞控制

5.6.1 拥塞

意义:防止网络中的流量超过了其处理能力,导致网络性能下降

  • 带宽不足:发送方发送的数据量超过了链路的带宽容量
  • 缓冲区溢出:路由器或交换机的缓冲区容量有限,如果数据包到达的速度超过了处理速度,缓冲区会被填满
  • 流量突发:突发流量可能导致短时间内网络资源被耗尽
  • 瓶颈链路:流量分布不均匀,可能使用带宽较低的瓶颈链路

拥塞窗口(cwnd):发送方根据网络拥塞状况动态调整的一个窗口,表示在当前网络条件下可以发送的数据量

发送窗口=min(cwnd,rwnd),通常情况下,接收窗口远大于拥塞窗口,因此通过调整 cwnd 就可以有效地控制发送速率

指导性原则

  • 何时减速:定时器超时、收到三个冗余ACK
  • 何时加速:收到正确ACK
  • 如何变速:发送方不断执行带宽探测
  • 加性增、乘性减(AIMD):加速是逐渐增加1个MSS,减小是直接对半砍或重置为1

最大报文段长度(Maximum Segment Size, MSS):单个TCP报文段的最大有效载荷大小,不包括TCP头部

5.6.2 机制

  1. 慢启动:设置 cwnd 的初始值是 1 个 MSS,每收到一个 ACK,cwnd 就乘 2
  2. 慢启动阈值:当慢启动增长到阈值的时候,进入拥塞避免阶段
  3. 拥塞避免:每收到一个 ACK,cwnd 就加 1
  4. 慢速恢复:如果发生超时事件,令ssthresh=cwnd/2,cwnd=1ssthresh = cwnd / 2, cwnd = 1,进入慢启动
  5. 快速恢复:如果收到3个冗余ACK,令ssthresh=cwnd/2,cwnd=ssthresh+3ssthresh = cwnd / 2, cwnd = ssthresh + 3,进入拥塞避免

既然能够收到冗余ACK,说明不是因为网络拥塞,而是因为某个分组丢失,说明此时路由器理应具备多传输3个负载数据的报文段的能力,但是却拿来传输冗余ACK了,所以应该加上3个MSS

5.6.3 算法

CUBIC算法:依据当前时间t与预计拥塞时间T的间隔

  • t<T:当t远离T的时候想要快速恢复,cwnd增长较快;当t接近T的时候变得谨慎,cwnd增长较慢
  • t>T:当t接近T的时候需要谨慎,cwnd增长较慢;当t远离T的时候想要快速找到新的平衡点,cwnd增长较快
特性TahoeRenoCUBIC
慢启动指数增长指数增长立方型增长
拥塞避免线性增长线性增长立方型增长
错误恢复慢启动超时则慢启动;冗余ACK则快速恢复立方型减缓恢复
适用场景一般网络一般网络高带宽、长延迟网络
恢复速度较快平滑且高效

5.6.4 其他方法

明确拥塞通告(Explicit Congestion Notification,ECN):允许路由器在检测到拥塞时,通过标记数据包头部中的 ECN 标志位,显式地通知发送方和接收方当前网络存在拥塞

基于时延的拥塞控制:通过监测和响应网络延迟来调整数据传输比例,主要关注时延的变化而不是关注丢包,目的是为了保持网络管道的最佳负载状态,从而避免拥塞和丢包

5.6.5 公平性

两条共享同一条传输速率为R的瓶颈链路的情况

  • 全带宽:两条连接的吞吐量之和为R
  • 平等带宽:两条连接的吞吐量相同

演变过程:在共享同一链路的多条 TCP 连接中,每条连接的发送速率会趋向于全带宽和平等带宽

  1. 在A点时,由于共同消耗的链路带宽小于R,两条连接都以相同的速率线性增长到B点
  2. 在B点时,由于共同消耗的链路带宽大于R,两条连接的吞吐量同时减半到C点
  3. 在C点时,由于共同消耗的链路带宽小于R,两条连接都以相同的速率线性增长到D点
  4. 以此类推,两条连接的带宽最终会收敛到平等带宽共享曲线和全带宽利用曲线的交叉点附近

6. QUIC

快速UDP互联网连接(Quick UDP Internet Connections,QUIC):是一种基于 UDP 的传输协议,但结合了 TCP、TLS 和 HTTP/2 的优点,旨在提供更快速、更安全的互联网连接

特征

  • 面向连接:使用连接ID来标识连接,通过一次握手建立QUIC连接状态
  • 安全:在应用层集成了加密机制,减少了传统TLS和TCP握手中的延迟
  • :允许在一个QUIC连接中管理多个独立的数据流,每个流可以独立进行数据传输和流量控制
  • 可靠:提供了类似于TCP的可靠数据传输机制,包括重传丢失的数据包和确保数据的顺序
  • 拥塞控制:实现了先进的拥塞控制算法,用于动态调整数据传输速率,以应对网络拥塞情况