第3章:传输层

1 传输服务和协议

  • 传输层为运行在不同主机上的应用进程提供逻辑通信

  • 传输协议运行在端系统

    • 发送方:将报文拆分成报文段,交给网络层

    • 接收方:将报文段合并为报文,交给应用

  • 协议可选择TCP和UDP

    • TCP:可靠的保序的传输

      • 多路复用,解复用

      • 流量控制

      • 拥塞控制

      • 面向连接

    • UDP:不可靠,不保序的传输

      • 多路复用,解复用

      • 没有为IP服务添加更多的额外服务

    • 都不提供时延和带宽保证的服务

2 多路复用和解复用

  • 在发送方主机多路复用:

    • 从多个套接字接收多个进程的报文,根据套接字对应的IP地址和端口等信息对报文段用头部加以封装(该头部信息用于以后的解复用)

  • 在接受方解复用

    • 根据报文段中的IP和端口信息将收到的报文段交给正确的套接字和对应的应用进程

多路解复用工作原理

  • 解复用作用:TCP或UDP实体根据某些信息,把报文段的数据部分交给正确的socket,从而交给正确的进程

  • 主机收到IP数据报

    • 每个数据报中包含源IP和目标IP

    • 每个数据报中包含一个数据段

    • 数据段有源端口和目标端口

  • 主机联合使用IP和端口将报文发给合适的套接字

3 无连接传输 UDP

UDP特性

  • 尽力而为的服务,报文段

    • 可能丢失

    • 可能乱序

  • 无连接:

    • UDP发送端和接收端之间没有握手

    • 每个UDP报文都被独立处理

  • UDP被用于:

    • 流媒体

    • DNS

    • SNMP

  • 在UDP上实现可靠传输

    • 在应用层增加可靠性

    • 应用特定的差错恢复

UDP:用户数据报协议

为什么需要UDP?

  • 不建立连接(会增加延时)

  • 简单:发送方和接收方没有连接状态

  • 报文段头部很小

  • 无拥塞控制和流量控制:可以尽可能快的发送报文段

![[第3章:传输层_time_1.png]]

UDP校验和

  • 目标:检测在被传输报文段中的差错

  • 发送方:

    • 将报文段的内容视为16比特的整数

    • 校验和:报文段的加法和(1的补运算)

    • 发送方将校验和放在UDP的校验和字段

  • 接受方:

    • 计算接收到的报文段的校验和

    • 判断是否和报文段中的校验和一致

4 可靠数据传输的原理

信道的不可靠特点决定了可靠数据传输协议(rdt)的复杂性

  • 使用有限状态机(FSM)来描述发送方和接收方

    • 状态:在该状态时,下一个状态只由下一个事件唯一确定

![[第3章:传输层_time_2.png]]

Rdt1.0:在可靠信道上的可靠数据传输

![[第3章:传输层_time_3.png]]

Rdt2.0:具有比特差错的信道

  • 下层信道可能会出错:将分组中的比特反转

    • 用校验和来检测比特差错

  • 问题:怎样从差错中恢复

    • 确认(ACK):接收方显式的告诉发送方分组已被正确接收

    • 否定确认(NACK):接收方显式告诉发送方分组出现了差错

      • 发送方接收到NACK后重传分组

    • rdt2.0新机制:采用差错控制编码进行差错检测

      • 发送方差错控制编码,缓存

      • 接收方使用编码捡错

      • 接收方的反馈:控制报文(ACK,NACK)

      • 发送方收到反馈相应的动作

![[第3章:传输层_time_4.png]]

rdt2.1 :ACK/NACK出错

  • 接收方发送的确认信号出错,导致发送方不知道具体信号

  • 引入新的机制:序号

    • 发送方在每个分组中加入序号

    • 如果ACK/NACK出错则发送方重传当前分组

    • 接收方丢弃重复分组,重新给信号

  • 停等协议: 发送方发送一个分组,然后等待接收方的应答

![[第3章:传输层_time_5.png]]

rdt2.2 : 无NACK的协议

  • 功能同rdt2.1,但只使用ACK

  • 接收方对最后正确接收的分组发ACK,以代替NAK

    • 接收方必须显式的包含正确接收分组的序号

  • 当收到重复的ACK时,发送方与收到NAK一样的动作:重传当前分组

  • 为后面的一次发送多个数据单位做一个准备

    • 一次能发送多个

    • 每一个的应答都有两个状态比较麻烦,不使用NAK确认信息减少一半,协议处理简单

![[第3章:传输层_time_6.png]]

rdt3.0: 具有比特差错和分组丢失的信道

  • 方法:发送方等待ACK一段合理的时间

  • 发送方超时重传

  • 问题:如果分组或ACK只是延时了

    • 重传会导致数据重复,但可以利用序列号解决这个问题

    • 接收方必须正确指明接收的序列号

  • 需要一个倒计时定时器

![[第3章:传输层_time_7.png]]

在链路容量比较大的情况下,性能很差

![[第3章:传输层_time_8.png]]

流水线协议

  • 流水线:允许在发送方未得到对方确认的情况下一次发送多个分组

    • 必须增加序号的范围:用多个bit表示分组的序号

    • 在发送方/接收方要有缓冲区

    • 两种通用的流水线协议:回退N步(GBN)和选择重传(SR)

  • 发送缓冲区:

    • 形式:内存中的一个区域,落入缓冲区的分组可以发送

    • 功能:用于存放已经发送但没有得到确认的分组

    • 必要性:需要重发时可用

  • 发送缓冲区的大小:一次最多可以发送多少个未经确认的分组

    • 停止等待=1

    • 流水线协议>1,不能过大,链路利用率不能超100%

  • 发送缓冲区中的分组

    • 未发送的:落入发送缓冲区的分组,可以连续发送出去

    • 已经发送出去的,等待对方确认的分组:发送缓冲区的分组只有得到确认才能剔除

滑动窗口协议-slide-window

  • 发送窗口:发送缓冲区内容的一个范围

    • 那些已发送但未得到确认分组的序号构成的空间

  • 发送窗口的最大值<=发送缓冲区的值

  • 一开始:没有发送任何一个分组

    • 后沿=前沿

    • 之间为发送窗口的尺寸=0

  • 每发送一个分组,前沿前移一个单位

  • 发送窗口的极限不能超过发送缓冲区

  • 发送窗口后沿移动

    • 条件:老分组得到确认

    • 结果:发送缓冲区落入新的分组,来了分组可以发送

    • 移动的极限:不能超过前沿

  • 接收窗口

    • 接收窗口=接收缓冲区

      • 接收窗口用于控制那些分组可以接收

        • 只有收到的分组序列号落入接收窗口内才允许接收

        • 如序号在接收窗口之外则丢弃

      • 接收窗口=1,则只能顺序接收

      • 接收窗口>1,则可以乱序接收

        • 但提交接收窗口之内的分组要按顺序

  • 正常情况下两个窗口的互动

    • 发送窗口:

      • 有新分组落入发送缓冲区范围,发送->前沿移动

      • 来了老的低序列号的确认->后沿向前移动->新的分组可以落入发送缓冲区的范围

    • 接收窗口:

      • 收到分组,落入接收缓冲窗口范围内,接收

      • 是低序列号,发送确认给对方

  • 异常情况下GBN的2窗口互动

    • 发送窗口:

      • 新分组落入发送缓冲区范围,发送->前沿移动

      • 超时重传机制让发送窗口内的所有分组重新发送

      • 来了老分组的重复确认->后沿不向前移动->新的分组无法落入发送缓冲区的范围

    • 接收窗口:

      • 收到乱序分组,没有落入到接收窗口范围内,丢弃

      • (重复)发送老分组的确认,累计确认

  • 异常情况下SR的2窗口互动

    • 发送窗口:

      • 新分组落入发送缓冲区范围,前沿向前移动

      • 收到乱序分组的确认,后沿无法向前移动,前沿无法移动,有新的分组无法落入到发送缓冲区访问

      • 每个分组维护一个超时计时器,哪个分组超时就重发哪个分组

    • 接收窗口:

      • 收到乱序分组,落入到接收缓冲区的范围内,接收

      • 单独发送该分组的确认

GBN协议和SR协议的异同

  • 相同:

    • 发送窗口>1

    • 一次性可以发送多个分组

  • 不同:

    • GBN的接收窗口=1

      • 接收端:只能按顺序接收

      • 发送端:从表现来看,一旦一个分组没有发送成功,这个分组后的所有分组都要重新发送

    • SR的接收窗口>1

      • 接收端可以乱序接收

      • 发送端可以只重传未确认或超时的分组

![[第3章:传输层_time_9.png]]

5 TCP协议

TCP特点

  • 点对点:

    • 一个发送方一个接收方

  • 可靠的、按顺序的字节流:

    • 没有报文边界

  • 管道化(流水线):

    • TCP拥塞控制和流量控制设置窗口大小

  • 全双工数据:

    • 在同一连接中数据双向流动

    • MSS:最大报文段大小

  • 面向连接:

    • 在数据交换之前,通过握手(交换控制报文)初始化发送方、接收方的状态变量

  • 有流量控制:

    • 发送方不会淹没接收方

5.1 TCP报文段结构

![[第3章:传输层_time_10.png]]

  • 序号:指的是载核的第一个字节在整个字节流中的偏移量

  • 确认号:如果ACK=555,则意味着接收方已经收到了554个字节

TCP往返延时和超时

  • 怎么设置TCP的超时?

    • 比RTT要长,但RTT是变化的

    • 太短:太早重传,无意义

    • 太长:对报文段丢失反应太慢

  • 怎么估计RTT?

    • sampleRTT:测量报文段从发送到收到确认的时间

      • 如果有重传,忽略此次测量

    • sampleRTT会变化,因此估计的RTT应该比较平滑

      • 对最近几个测量做平均值

![[第3章:传输层_time_11.png]]

![[第3章:传输层_time_12.png]]

5.2 TCP如何做RDT

  • TCP在IP不可靠服务的情况下建立了rdt

    • 管道化的报文段

      • GBN or SR

    • 累计确认(GBN)

    • 单个重传定时器(GBN)

    • 是否可以乱序接收,没有规范,可以丢弃也可以缓存

  • 通过以下事件触发重传

    • 超时(只重发那个最早未确认的段:SR)

    • 重复的确认

TCP ACK产生的建议

接收方事件
接收方动作

所期望的序列号的报文段按序到达。所有在期望序列号之前的数据都已经被确认

延迟的ACK,对另一个报文段的到达最多等待500ms。如果下一个报文段在这个时间间隔内没有到达则发送一个ACK

有期望序号的报文段到达,另一个按序报文段等待发送ACK

立即发送单个累计ACK,以确认两个按序报文段

比期望序列号大的报文段乱序到达,检测出数据流中的间隔

立即发送重复ACK,指明下一个期待字节的序号

能部分或完全填充接收数据间隔的报文段到达

若该报文段起始于间隔的低端,则立即发送ACK

快速重传

  • 超时周期往往太长:在重传丢失报文段之前的延时太长

  • 通过重复的ACK来检测报文丢失

    • 发送方通常发送大量的报文段

    • 如果报文段丢失会引起多个重复的ACK

  • 如果发送方收到同一数据的3个冗余ACK,重传最小序号的段:

    • 快速重传:在定时器过时之前重发报文段

5.3 流量控制

  • 接收方控制发送方,不让发送方发送太多、太快以至于让接收方的缓存溢出

  • 接收方在向发送方的TCP段头部的rwnd字段通告其空闲buffer大小

    • RcvBuffer大小通过socket选项设置,通常默认为4096个字节

    • 很多操作系统自动调整rcvBuffer

  • 发送方限制未确认的字节个数<=接收方发送过来的rwnd值,保证接收方不会被淹没

  • 缓存中可用空间(假设TCP接收方丢弃乱序的报文段)= RcvWindow = RcvBuffer - 【LastByteRcvd - LastByteRead】

  • 处理“零窗口”死锁:如果接收方缓存已满,它会通告一个 rwnd = 0,这称为零窗口(Zero Window),发送方必须暂停发送。但如果之后接收方缓存有空余,重新通告的非零窗口报文丢失了,双方就会陷入“死等”。为解决这个问题,TCP引入了持续计时器(Persistence Timer)。当发送方收到零窗口通知后,会启动此计时器。超时后,发送方会发送一个**零窗口探测(Zero Window Probe)**​ 报文(通常只含1字节数据),接收方在回应此探测报文时,会再次告知当前窗口大小,从而打破僵局

5.4 连接管理

在正式交换数据之前,发送方和接收方建立通信关系:

  • 同意连接(每一方都知道对方愿意建立连接)

  • 同意连接参数初始化,资源初始化

![[第3章:传输层_time_13.png]]

连接释放

  • 客户端,服务端分别关闭它这一侧的连接

    • 发送FIN=1的报文段

  • 一旦收到FIN,使用ACK回应

    • 接收到FIN段,ACK可以和它发出的FIN段一起发送

  • 可以处理同时的FIN交换

  • 对称释放并不完美,两军问题

5.5 拥塞控制

拥塞

  • 非正式的定义:太多的数据需要网络传输,超过了网络的处理能力

  • 与流量控制不同,拥塞的表现:

    • 分组丢失(路由器缓冲区溢出)

    • 分组经历较长的延迟(在路由器的队列中排队)

拥塞的代价

  • 为了达到一个有效输出,网络需要作更多的工作(重传)

  • 没有必要的重传,链路中包括了多个分组的拷贝

    • 是那些没有丢失,经历的时间比较长(拥塞状态)但是超时的分组

    • 降低了"goodput"

  • 当分组丢失,任何关于这个分组的上游传输能力都被浪费了

拥塞控制方法

  • 端到端拥塞控制:

    • 没有来自网络的显示反馈

    • 端系统根据延迟和丢失事件判断是否有拥塞

    • TCP采用的方法

  • 网络辅助的拥塞控制:

    • 路由器提供给端系统以反馈信息

      • 单个bit置位,显示有拥塞

      • 显式提供发送端可以采用的速率

5.6 TCP拥塞控制

TCP拥塞控制:机制

  • 端到端的拥塞控制机制

    • 路由器不向主机反馈有关拥塞的信息

      • 路由器的负担比较轻

      • 符合网络核心简单的TCP/IP架构原则

  • 端系统根据自身得到的信息判断是否拥塞从而采取动作

  • 拥塞控制的几个问题

    • 如何检测拥塞:

      • 轻微拥塞

      • 拥塞

    • 控制策略

      • 在拥塞时如何采用动作降低速率

      • 在拥塞缓解时如何采用动作增加速率

拥塞感知

  • 某个段超时了(丢失事件):拥塞

    • 超时时间到,某个段的确认没有来

    • 原因1:网络拥塞(某个路由器的缓存满了被丢弃)概率大

    • 原因2:分组的差错检查没有通过被丢弃,概率下

    • 一旦超时,就认为拥塞了,有一定误判,但是总体控制方向是对的

  • 有关某个段的3次重复ACK:轻微拥塞

    • 段的第一个ACK:正常,确认绿段,等待红段

    • 段的第二个重复ACK:意味着红段的后一段收到了,蓝段乱序到达

速率控制

  • 维持一个拥塞窗口的值:CongWin

  • 发送端限制已发送但未确认的数据量:

    • LastByteSent - LastByteAcked <= CongWin

  • 从而粗略的控制发送方往网络中注入的速率

  • Rate = CongWin/RTT bytes/sec

  • CongWin是动态的,是感知到的网络拥塞程度的函数

    • 超时或3个重复ack:Congwin下降

      • 超时时:CongWin降为1MSS,进入ss节点然后再倍增到CongWin/2(每个RTT),从而进入CA阶段

      • 3个重复的ACK:CongWin降为CongWin/2,进入CA阶段

    • 否则(正常收到ACK,没有发生以上情况):CongWin上升

      • SS阶段:加倍增加(每RTT)

      • CA阶段:线性增加(每RTT)

  • 联合控制的方法

    • 发送端控制发送未确认的量同时也不能超过接收窗口,满足流量控制要求

      • sendwin = min(CongWin,recvwin)

      • 同时满足拥塞控制和流量控制

  • 拥塞控制策略:

    • 慢启动

    • AIMD:线性增,乘性减

    • 超时时间后的保守策略

5.6.1 TCP慢启动

连接刚建立,CongWin = 1 MSS

  • 如 MSS = 1460 bytes & RTT = 200 msec

  • 初始速率 = 58.4kbps

可用带宽可能 >> MSS/RTT

  • 应该尽可能加速,达到希望的速率

当连接开始时,指数性增加发送速率,直到发生丢失的事件

  • 初始的速率很慢,但是增加速度很快

慢启动过程

  • 当连接开始时,指数性增加发送速率直到发生丢失事件

    • 每一个RTT,CongWin加倍

    • 慢启动阶段:只要不超时或3个重复ACK,一个RTT,CongWin加倍

  • 总结:初始速率很慢,但是加速很快,从长期来看可以忽略

5.6.2 AIMD

MD:Multiplicative Decrease

丢失事件后将CongWin降为1,将CongWin/2作为阈值,进入慢启动阶段(倍增直到CongWin/2)

AI:Additive Increase

当CongWin > 阈值时,一个RTT如没有发生丢失事件,将CongWin加1MSS:探测

实现

  • 变量:Threshold

  • 出现丢失,Threshold设置成CongWin的一半

5.6.3 总结

  • 当CongWin < Threshold , 发送端处于慢启动阶段,窗口指数增加

  • 当CongWin > Threshold,发送端处于拥塞避免节点(congestion-avoidance),窗口线性增长

  • 当收到三个重复的ACK,Threshold设置为CongWin的一半,CongWin变为Threshold + 3

  • 当发生超时事件,CongWin设置为1MSS,Threshold设置为CongWin/2,进入ss阶段

事件
状态
TCP 发送端行为
解释

以前没有收到ACK的data被ACKed​ (正常收到新确认)

慢启动 (SS)

CongWin = CongWin + MSS 如果 CongWin > Threshold(阈值),则状态变为“拥塞避免”(CA)

指数增长​ 每一个RTT(往返时间),CongWin翻倍,快速探测可用带宽。

以前没有收到ACK的data被ACKed​ (正常收到新确认)

拥塞避免 (CA)

CongWin = CongWin + MSS * (MSS / CongWin)

加性增长​ 每一个RTT,CongWin只增加 1 个MSS,缓慢线性增加,趋于稳定。

通过收到3个重复的ACK,发现丢失的事件​ (快速重传)

SS 或 CA

Threshold = CongWin / 2 CongWin = Threshold + 3 状态变为“CA”

乘性减​ 网络出现拥塞,但情况不严重。CongWin减半,但不重置为1,进入拥塞避免阶段。

超时

SS 或 CA

Threshold = CongWin / 2 CongWin = 1 MSS 状态变为“SS”

网络拥塞严重​ 认为有报文丢失,将CongWin重置为1,重新开始慢启动过程。

重复的ACK

SS 或 CA

对被确认的报文段,增加重复ACK的计数

中间状态​ CongWin和阈值(Threshold)保持不变,等待后续事件(如满3个ACK触发快速重传)。

5.7 TCP吞吐量

**TCP的平均吞吐量是多少,使用窗口window尺寸W和RTT来描述?

○ 忽略慢启动阶段,假设发送端总有数据传输

W: 发生丢失事件时的窗口尺寸(单位:字节)

○ 平均窗口尺寸(#in-flight字节):3/4 W

○ 平均吞吐量:RTT时间吞吐3/4 W

○ 平均TCP吞吐量 = (3/4 W) / RTT

![[第3章:传输层_time_14.png]]

5.8 TCP的公平性

公平性目标:如果k个连接共享一个带宽为R的瓶颈,每一个会话的有效带宽为R/K。

![[第3章:传输层_time_15.png]]

公平性和UDP

  • □ 多媒体应用通常不是用TCP

    • ● 应用发送的数据速率希望不受拥塞控制的节制

  • □ 使用UDP:

    • ● 音视频应用泵出数据的速率是恒定的,忽略数据的丢失

  • □ 研究领域: TCP友好性

公平性和并行TCP连接

  • □ 2个主机间可以打开多个并行的TCP连接

  • □ Web浏览器

  • □ 例如: 带宽为R的链路支持了9个连接;

    • 如果新的应用要求建1个TCP连接,获得带宽 R/10

    • 如果新的应用要求建11个TCP连接,获得带宽 R/2

最后更新于