Skip to content

2 传输层

3134字约10分钟

2022-06-09

计算机网络传输层:应用进程到应用进程的通信。

运输层与网络层的功能对比:运输层关心的是应用进程到应用进程的通信,网络层关心的是主机到主机的通信。

运输层协议必须提供

  • 多路复用/多路分解
  • 差错检查

UDP

UDP (User Datagram Protocol)的主要特点:

  • 无连接的
  • 尽力而为交付
  • 面向报文,既不拆分又不合并
  • 无拥塞控制
  • 支持一对一、一对多、多对一和多对多的交互通信
  • 首部开销小,只有 8 个字节

UDP 数据报结构

image-20211201145332397

★ 检查和的计算

image-20211201152915435

要点:伪首部、首部、数据一起求和(进位回卷),最后取反。

RDT 可靠数据传输原理

数据可靠传输要求:

  • 不出错

    • 差错检测
    • 接收方反馈
    • 检错重传
  • 不丢包

    • 接收方反馈
    • 超时重传机制
    • 序号机制
  • 不乱序

    • 接收方反馈
    • 序号机制(还可以识别重复分组)

对接收方反馈进行确认的方式:累计确认、选择确认、捎带确认

简单停等协议

发送方与接收方维护一个分组大小的缓冲区。序号为 0,1

提升信道利用率——流水线技术,引入滑动窗口

GBN 协议

image-20211201163000458

发送方维护一个有多个分组缓冲区的滑动窗口,接收方维护一个分组缓冲区。

发送方一次可以发多个分组,接收方仅接受期待的那个分组(乱序、出错均被丢弃)。

发送方维护一个基序号定时器。

累积确认:当收到一个分组到达 ACK 时,意味着基序号到已被确认的 ACK 序号之间均到达(因为接受方只接受期待的分组)可以一并确认。

发送方累积确认,滑动窗口并重设定时器。

回退 N (Go-Back-N):指发送方基序号定时器时间到(或丢包或出错或延时长),需要将从基序号开始所有已发送的包全部再发送一遍(不能确定这些包是否已到达,就要重发)。

SR 协议

image-20211201163715977

发送方与接收方各维护多个分组的缓冲区。

发送方可以一次发送多个分组,接收方可以接收范围内的失序分组。

发送方为每一个已发送分组维护定时器,接收方对每一个接收分组进行 ACK 确认。

定时器到,仅重发这一个分组(即选择重发 SR)。

当发送基序号已被确认可滑动发送窗口,当接收方基序号已被接收可滑动接收窗口。

GBN 与 SR 简单对比

对于 k 位编号的窗口范围?

(⚠️ 接收方窗口不大于发送窗口 —— 否则没意义)

(⚠️ 发送窗口和接收窗口序号不能重叠[这里重叠指接收窗口右部分与发送窗口左部分交叉]否则出大问题)

发送端窗口 + 接收端窗口2k \text{发送端窗口 + 接收端窗口} \le 2^k

GBN:

  • $ \text{发送端} \le 2^ k -1$
  • 接收端=1\text{接收端} = 1

SR:

接收方窗口2k1 \text{接收方窗口}\le 2^{k-1}

GBNSR
确认方式累积确认单个确认
定时器对所有已发送但未确认的分组统一设置一个定时器对所有已发送但未确认的分组分别设置定时器
超时(n)重传分组n和窗口中所有序号大于n的分组仅重传分组n
失序分组丢弃 (不缓存) -> 接收方无缓存!缓存
重发按序到达的最高序号分组的ACK对失序分组进行选择性确认

★ TCP

TCP 作用:在不可靠(丢失、乱序、出错)信道上实现了可靠的数据传输。

TCP 的特点:

  • 可靠传输
  • 基于字节流(对于用户程序,可能存在 short read/write 所谓粘包)
  • 面向连接(握手建立连接,挥手断开连接)
  • 点对点
  • 全双工

TCP 报文段首部结构

image-20211201132222147

  • 源端口和目的端口:实现复用/分用。
  • 序号:TCP 连接面向字节编号(报文段序号)。
  • 确认号:是期望下一个报文段的第一个数据字节的序号。
  • 数据偏移:由于首部长度可变,指出了数据偏移(也是TCP 首部长度),以 4 字节为单位。
  • 标志位:
    • URG:表明紧急指针字段有效,要求尽快传送。
    • ACK :表明确认号字段有效,连接建立后所有报文段都必须把 ACK 置 1
    • PSH :表明该报文断需要尽快交付,不需要等待缓存满
    • RST :表明 TCP 连接中国出现了严重差错必须释放连接然后重新建立连接。还可以用来拒绝一个非法的报文段或拒绝打开一个连接。
    • SYN :在连接建立时用来同步序号,要求建立连接。
    • FIN :请求是释放运输连接。
  • 窗口:自己的接收窗口大小。为发送方设置其发送窗口的依据。

TCP 可靠数据传输

NextSeqNum:下一个待发送的字节编号

SendBase:表示最早未确认的字节编号

从上层收到数据

  • 生成具有 NextSeqNum 的 TCP 报文段
  • 如果定时器没有在运行,则启动定时器。
  • 向网络层传递报文段。
  • NextSeqNum+=len(data)NextSeqNum += len(data)

Nagle 算法:当一个 TCP 连接中有在传数据未被确认,小的报文段就不能被发送。当收到 ACK 后,将这些小数据整合到一个报文段发送。

收到序号为 y 的 ACK

如果 y>sendBasesendBase=yy > sendBase\text{,}sendBase = y;如果当前有未被确认的报文段则重新启动定时器,否则关闭。

定时器超时

  • 重传具有最小序号但未应答的报文段。
  • 重新启动定时器。

发生重传时,设置的新的超时时间间隔为之前的两倍;当收到上层数据或收到 ACK 时重新推算。

快速重传机制

如果收到三个冗余的 ACK,则立即重发所指示的报文段。

作用:快速探测丢包,并从丢包中恢复。

延迟 ACK 机制

事件接收方动作
具有期望序号的报文段到达,所有之前的数据都已确认延迟 ACK (最多 500ms)2
具有期望序号的报文段到达,此前一个 ACK 在等待立即发送 ACK
比期望序号大的报文段到达立即发送冗余 ACK
报文填充间隔,且起始于低端立即发送 ACK

⚠️:与 Nagle 算法一起使用可能导致死锁。

TCP 超时只发送一个数据,累积确认(GBN),缓存一定范围内的乱序分组(SR)

TCP 流量控制

TCP 让发送方维护一个成为接收窗口的变量,以告知接收方自己还有多少可用的缓冲空间。(TCP 是全双工通信,因此两边各维护一个接收窗口)——通知窗口,可变滑动窗口

rwnd=RcvBuffer(LastByteRcvedLastByteRead) rwnd = RcvBuffer - (LastByteRcved - LastByteRead)

那么发送方根据对方的接收窗口满足公式:

LastByteSentLastByteAckedrwnd LastByteSent - LastByteAcked \le rwnd

当接收窗口满的情况?

当接收方的接收窗口为 0 时,发送方继续发送只有一个字节数据的报文段,接收方确认这些报文段并不断更新 rwnd 的值直到缓存开始清空,rwnd 不再为 0.

TCP 超时重传机制

超时间隔长度设置:

  • 太短:过早超时,造成不必要的重传
  • 太长:当发生丢包时,发送方反映太慢,导致数据传输时延大
  • 理想状况:超时间隔长度设置应略大于链接的往返时间(RTT)

SampleRTT:表示报文段被发出到报文段被确认之间的时间量。(决不为已重传的报文段估计 原因:区分不出确认包是新的还是旧的)

EstimatedRTT:TCP 维持的一个 SampleRTT 的加权均值。

EstimatedRTT=(1α)×EstimatedRTT+α×SampleRTT (α=0.125) EstimatedRTT = (1-\alpha)\times EstimatedRTT + \alpha \times SampleRTT \ (\alpha = 0.125)

EstimatedRTT 加权平均公式,从统计学的观点来说,被称为指数加权移动平均,这种加权平均对最近样本赋予的权值要大于对老样本赋予的权值。其中 α\alpha 的值是 TCP 的一个经验值。

EstimatedRTT=(1α)n×t0+(1α)n1×α×t1+...+α×tn EstimatedRTT = (1-\alpha)^n\times t_0 + (1-\alpha)^{n-1}\times \alpha \times t_1 + ... + \alpha \times t_n

EstimatedRTT 的指数表达形式,其中 SampleRTT,依次取值 t0,t1,t2,...,tnt_0, t_1, t_2, ..., t_n,EstimatedRTT 初始值为 t0t_0.

DevRTT:表示 EstimatedRTT 与 SampleRTT 的偏离程度。

DevRTT=(1β)×DevRTT+β×SampleRTTEstimatedRTT (β=0.25) DevRTT = (1-\beta )\times DevRTT + \beta \times \mid{SampleRTT-EstimatedRTT}\mid\ (\beta = 0.25)

DevRTT 初始值取 0.5×SampleRTT0.5\times SampleRTT,DevRTT 是 SampleRTT 与 EstimatedRTT 之间差值的指数加权移动平均。

TimwoutInterval:设置的超时重传阈值。

TimeoutInterval=EstimatedRTT+4×DevRTT TimeoutInterval = EstimatedRTT + 4 \times DevRTT

RFC 推荐的初始 TimeoutInterval 的值为 1 秒,当出现超时后,TimeoutInterval 加倍,防止出现过早超时现象,然而收到报文段就更新 EstimatedRTT,再使用上述公式计算 TimeoutInterval.

TCP 连接管理

建立连接——三次握手 🤝

image-20211201165627124

第一次 🤝 :发送方发送 SYN 信号并发送自己的序列号「请求建立连接,告知序列号」

第二次 🤝 :接收方发送 ACK 信号并发送自己的序列号「回应连接,告知序列号」

第三次 🤝 :可携带数据(捎带确认 ACK)

三次握手的必要性,TCP 是全双工信道,需要确保双方知道对方收发能力正常。

第一次握手成功,接收方知晓发送方发送能力正常。

第二次握手成功,发送方知道接收方的发送、接收能力正常。

第三次握手成功,接收方知晓发送方接收能力正常。

断开连接——四次挥手 🙋

image-20211201171646837

第一次挥手 🙋 :一方发送 FIN 报文表示自己可以断开连接了。

第二次挥手 🙋 :另一方对 FIN 报文给予 ACK 响应。

第三次挥手 🙋 :另一方发完东西可以断开连接了,发送 FIN 报文。

第四次挥手 🙋 : 这一方收到 FIN 报文给予 ACK 响应。

TimeWait 2MSL:防止 ACK 报文丢失导致另一方未收到自己的响应导致未关闭。当另一方等待重传 FIN 报文,则这一方需要等待 2 MSL 时间对可能进行重传的 FIN 报文进行响应。


TCP 拥塞控制

TCP 提供端到端的拥塞控制。TCP 额外维护了一个叫做拥塞窗口的变量,其中发送数据量满足

LastByteSentLastByteAckedmin{cwnd, rwnd} LastByteSent-LastByteAcked \le \min \{cwnd,\ rwnd\}

TCP 拥塞控制算法主要包括三个主要部分:1⃣️ 慢启动 2⃣️ 拥塞避免 3⃣️ 快速恢复

1⃣️ 慢启动

连接开始时,cwnd 通常设置为一个 MSS 的较少值,在这个阶段中每收到一个确认报文段则增加一个 MSS,这个过程每经过一个 RTT 的时间,发送速率就翻一番(指数增长)。

当检测到 cwnd 等于 ssthresh 时,结束慢启动并且进入拥塞避免模式。

2⃣️ 拥塞避免

在拥塞避免阶段,每过一个 RTT 将拥塞窗口值增加一个 MSS。

3⃣️ 快速恢复

当存在超时事件时,TCP 发送方将 cwnd 设置为 1 并开启慢启动过程,并将 ssthresh 更新为 cwnd / 2。

当检测到 3 个冗余 ACK 后,将 cwnd 的值更新为 cwnd / 2 + 3 * MSS,将 ssthresh 设置为 cwnd / 2.(Reno 算法,早期的 Tahoe 算法在这里 cwnd 置为 1),然后进入拥塞避免。

image-20211201200033423

TCP 的吞吐量

考虑吞吐量指标时一般忽略慢启动过程(指数增长),考虑窗口一直在拥塞避免状态;

假定丢包事件发生时,窗口大小为 W,吞吐量为 W/RTT;

丢包事件发生后,窗口大小减为 W/2,吞吐量为 W/2RTT;

那么平均吞吐量为 0.75 W/RTT.

吞吐量是丢包率(L)的函数:

吞吐量=1.22×MSSRTTL \text{吞吐量}=\frac {1.22\times MSS}{RTT \sqrt{L}}

TCP 的公平性

  • 公平性的目标:如果 K 个 TCP 连接共享同一个带宽为 R 的瓶颈链路,那么每个连接的平均带宽为 R / K.
  • 无法阻止应用在两个主机之间建立多个并行的连接。

image-20211201201855565