2 传输层
3134字约10分钟
2022-06-09
计算机网络传输层:应用进程到应用进程的通信。
运输层与网络层的功能对比:运输层关心的是应用进程到应用进程的通信,网络层关心的是主机到主机的通信。
运输层协议必须提供:
- 多路复用/多路分解
- 差错检查
UDP
UDP (User Datagram Protocol)的主要特点:
- 无连接的
- 尽力而为交付
- 面向报文,既不拆分又不合并
- 无拥塞控制
- 支持一对一、一对多、多对一和多对多的交互通信
- 首部开销小,只有 8 个字节
UDP 数据报结构
★ 检查和的计算
要点:伪首部、首部、数据一起求和(进位回卷),最后取反。
RDT 可靠数据传输原理
数据可靠传输要求:
不出错
- 差错检测
- 接收方反馈
- 检错重传
不丢包
- 接收方反馈
- 超时重传机制
- 序号机制
不乱序
- 接收方反馈
- 序号机制(还可以识别重复分组)
对接收方反馈进行确认的方式:累计确认、选择确认、捎带确认
简单停等协议
发送方与接收方维护一个分组大小的缓冲区。序号为 0,1
提升信道利用率——流水线技术,引入滑动窗口
GBN 协议
发送方维护一个有多个分组缓冲区的滑动窗口,接收方维护一个分组缓冲区。
发送方一次可以发多个分组,接收方仅接受期待的那个分组(乱序、出错均被丢弃)。
发送方维护一个基序号定时器。
累积确认:当收到一个分组到达 ACK 时,意味着基序号到已被确认的 ACK 序号之间均到达(因为接受方只接受期待的分组)可以一并确认。
发送方累积确认,滑动窗口并重设定时器。
回退 N (Go-Back-N):指发送方基序号定时器时间到(或丢包或出错或延时长),需要将从基序号开始所有已发送的包全部再发送一遍(不能确定这些包是否已到达,就要重发)。
SR 协议
发送方与接收方各维护多个分组的缓冲区。
发送方可以一次发送多个分组,接收方可以接收范围内的失序分组。
发送方为每一个已发送分组维护定时器,接收方对每一个接收分组进行 ACK 确认。
定时器到,仅重发这一个分组(即选择重发 SR)。
当发送基序号已被确认可滑动发送窗口,当接收方基序号已被接收可滑动接收窗口。
GBN 与 SR 简单对比
对于 k 位编号的窗口范围?
(⚠️ 接收方窗口不大于发送窗口 —— 否则没意义)
(⚠️ 发送窗口和接收窗口序号不能重叠[这里重叠指接收窗口右部分与发送窗口左部分交叉]否则出大问题)
发送端窗口 + 接收端窗口≤2k
GBN:
- $ \text{发送端} \le 2^ k -1$
- 接收端=1
SR:
接收方窗口≤2k−1
GBN | SR | |
---|---|---|
确认方式 | 累积确认 | 单个确认 |
定时器 | 对所有已发送但未确认的分组统一设置一个定时器 | 对所有已发送但未确认的分组分别设置定时器 |
超时(n) | 重传分组n和窗口中所有序号大于n的分组 | 仅重传分组n |
失序分组 | 丢弃 (不缓存) -> 接收方无缓存! | 缓存 |
重发按序到达的最高序号分组的ACK | 对失序分组进行选择性确认 |
★ TCP
TCP 作用:在不可靠(丢失、乱序、出错)信道上实现了可靠的数据传输。
TCP 的特点:
- 可靠传输
- 基于字节流(对于用户程序,可能存在 short read/write 所谓粘包)
- 面向连接(握手建立连接,挥手断开连接)
- 点对点
- 全双工
TCP 报文段首部结构
- 源端口和目的端口:实现复用/分用。
- 序号:TCP 连接面向字节编号(报文段序号)。
- 确认号:是期望下一个报文段的第一个数据字节的序号。
- 数据偏移:由于首部长度可变,指出了数据偏移(也是TCP 首部长度),以 4 字节为单位。
- 标志位:
- URG:表明紧急指针字段有效,要求尽快传送。
- ACK :表明确认号字段有效,连接建立后所有报文段都必须把 ACK 置 1
- PSH :表明该报文断需要尽快交付,不需要等待缓存满
- RST :表明 TCP 连接中国出现了严重差错必须释放连接然后重新建立连接。还可以用来拒绝一个非法的报文段或拒绝打开一个连接。
- SYN :在连接建立时用来同步序号,要求建立连接。
- FIN :请求是释放运输连接。
- 窗口:自己的接收窗口大小。为发送方设置其发送窗口的依据。
TCP 可靠数据传输
NextSeqNum:下一个待发送的字节编号
SendBase:表示最早未确认的字节编号
从上层收到数据:
- 生成具有 NextSeqNum 的 TCP 报文段
- 如果定时器没有在运行,则启动定时器。
- 向网络层传递报文段。
- NextSeqNum+=len(data)
Nagle 算法:当一个 TCP 连接中有在传数据未被确认,小的报文段就不能被发送。当收到 ACK 后,将这些小数据整合到一个报文段发送。
收到序号为 y 的 ACK:
如果 y>sendBase,sendBase=y;如果当前有未被确认的报文段则重新启动定时器,否则关闭。
定时器超时:
- 重传具有最小序号但未应答的报文段。
- 重新启动定时器。
发生重传时,设置的新的超时时间间隔为之前的两倍;当收到上层数据或收到 ACK 时重新推算。
快速重传机制:
如果收到三个冗余的 ACK,则立即重发所指示的报文段。
作用:快速探测丢包,并从丢包中恢复。
延迟 ACK 机制:
事件 | 接收方动作 |
---|---|
具有期望序号的报文段到达,所有之前的数据都已确认 | 延迟 ACK (最多 500ms)2 |
具有期望序号的报文段到达,此前一个 ACK 在等待 | 立即发送 ACK |
比期望序号大的报文段到达 | 立即发送冗余 ACK |
报文填充间隔,且起始于低端 | 立即发送 ACK |
⚠️:与 Nagle 算法一起使用可能导致死锁。
TCP 超时只发送一个数据,累积确认(GBN),缓存一定范围内的乱序分组(SR)
TCP 流量控制
TCP 让发送方维护一个成为接收窗口的变量,以告知接收方自己还有多少可用的缓冲空间。(TCP 是全双工通信,因此两边各维护一个接收窗口)——通知窗口,可变滑动窗口
rwnd=RcvBuffer−(LastByteRcved−LastByteRead)
那么发送方根据对方的接收窗口满足公式:
LastByteSent−LastByteAcked≤rwnd
当接收窗口满的情况?
当接收方的接收窗口为 0 时,发送方继续发送只有一个字节数据的报文段,接收方确认这些报文段并不断更新 rwnd 的值直到缓存开始清空,rwnd 不再为 0.
TCP 超时重传机制
超时间隔长度设置:
- 太短:过早超时,造成不必要的重传
- 太长:当发生丢包时,发送方反映太慢,导致数据传输时延大
- 理想状况:超时间隔长度设置应略大于链接的往返时间(RTT)
SampleRTT:表示报文段被发出到报文段被确认之间的时间量。(决不为已重传的报文段估计 原因:区分不出确认包是新的还是旧的)
EstimatedRTT:TCP 维持的一个 SampleRTT 的加权均值。
EstimatedRTT=(1−α)×EstimatedRTT+α×SampleRTT (α=0.125)
EstimatedRTT 加权平均公式,从统计学的观点来说,被称为指数加权移动平均,这种加权平均对最近样本赋予的权值要大于对老样本赋予的权值。其中 α 的值是 TCP 的一个经验值。
EstimatedRTT=(1−α)n×t0+(1−α)n−1×α×t1+...+α×tn
EstimatedRTT 的指数表达形式,其中 SampleRTT,依次取值 t0,t1,t2,...,tn,EstimatedRTT 初始值为 t0.
DevRTT:表示 EstimatedRTT 与 SampleRTT 的偏离程度。
DevRTT=(1−β)×DevRTT+β×∣SampleRTT−EstimatedRTT∣ (β=0.25)
DevRTT 初始值取 0.5×SampleRTT,DevRTT 是 SampleRTT 与 EstimatedRTT 之间差值的指数加权移动平均。
TimwoutInterval:设置的超时重传阈值。
TimeoutInterval=EstimatedRTT+4×DevRTT
RFC 推荐的初始 TimeoutInterval 的值为 1 秒,当出现超时后,TimeoutInterval 加倍,防止出现过早超时现象,然而收到报文段就更新 EstimatedRTT,再使用上述公式计算 TimeoutInterval.
TCP 连接管理
建立连接——三次握手 🤝
第一次 🤝 :发送方发送 SYN 信号并发送自己的序列号「请求建立连接,告知序列号」
第二次 🤝 :接收方发送 ACK 信号并发送自己的序列号「回应连接,告知序列号」
第三次 🤝 :可携带数据(捎带确认 ACK)
三次握手的必要性,TCP 是全双工信道,需要确保双方知道对方收发能力正常。
第一次握手成功,接收方知晓发送方发送能力正常。
第二次握手成功,发送方知道接收方的发送、接收能力正常。
第三次握手成功,接收方知晓发送方接收能力正常。
断开连接——四次挥手 🙋
第一次挥手 🙋 :一方发送 FIN 报文表示自己可以断开连接了。
第二次挥手 🙋 :另一方对 FIN 报文给予 ACK 响应。
第三次挥手 🙋 :另一方发完东西可以断开连接了,发送 FIN 报文。
第四次挥手 🙋 : 这一方收到 FIN 报文给予 ACK 响应。
TimeWait 2MSL:防止 ACK 报文丢失导致另一方未收到自己的响应导致未关闭。当另一方等待重传 FIN 报文,则这一方需要等待 2 MSL 时间对可能进行重传的 FIN 报文进行响应。
TCP 拥塞控制
TCP 提供端到端的拥塞控制。TCP 额外维护了一个叫做拥塞窗口的变量,其中发送数据量满足
LastByteSent−LastByteAcked≤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),然后进入拥塞避免。
TCP 的吞吐量
考虑吞吐量指标时一般忽略慢启动过程(指数增长),考虑窗口一直在拥塞避免状态;
假定丢包事件发生时,窗口大小为 W,吞吐量为 W/RTT;
丢包事件发生后,窗口大小减为 W/2,吞吐量为 W/2RTT;
那么平均吞吐量为 0.75 W/RTT.
吞吐量是丢包率(L)的函数:
吞吐量=RTTL1.22×MSS
TCP 的公平性
- 公平性的目标:如果 K 个 TCP 连接共享同一个带宽为 R 的瓶颈链路,那么每个连接的平均带宽为 R / K.
- 无法阻止应用在两个主机之间建立多个并行的连接。