计算机网络:运输层
概述和传输层服务
传输服务和协议
-
为运行在不同主机上的应用进程提供逻辑通信
-
传输协议运行在端系统
发送方
:将应用层的报文分成报文段,然后传递给网络层接受方
:将报文段重组成报文,然后传递给应用层 -
有多个传输层协议可供应用选择
Internet
:TCP和UDP
网络层 vs 运输层
- 网络层服务:主机之间的逻辑通信
- 传输层服务:进程之间的逻辑通信
- 依赖于网络层的服务:
延时
,带宽
- 并对网络层的服务进行增强:
数据丢失
、顺序混乱
、加密
。
- 依赖于网络层的服务:
Internet传输层协议
- 可靠的、保序的传输:TCP
- 多路复用、解复用
- 拥塞控制
- 流量控制
- 建立连接
- 不可靠的、不保序的传输:UDP
- 多路复用、解复用(进程到进程)
- 没有为尽力而为的IP服务提供更多的其他额外的服务
- 都不提供的服务:
- 延时保证
- 带宽保证
一个四元组只要有一个不一样,那他们就定位到不同的socket,从而发给不同的应用进程。
多路分解和多路复用
多路解复用工作原理
- 解复用作用:TCP或UDP实体采用哪些信息,将报文段的数据部分交给正确的socket,从而交给正确的进程
- 主机收到IP数据报
- 每个数据报有源IP地址和目标IP地址
- 每个数据报承载一个传输层报文段
- 每个报文段有一个源端口号和目标端口号
- 主机联合使用IP地址和端口号将报文段发送给合适的套接字
无连接传输UDP
UDP:用户数据报协议
-
不建立连接(会增加延时)
-
简单:在发送端和接收端没有连接状态
-
报文段的头部很小(开销小)
-
无拥塞控制和流量控制:
UDP可以尽可能快的发送报文
应用->传输的速率 = 主机->网络的速率
为什么叫做数据报?因为不需要建立连接
UDP校验和
目标: 检测在被传输报文段中的差错 (如比特反转 )
发送方:
- 将报文段的内容视为16 比特的整数
- 校验和:报文段的加法和(1的补运算)
- 发送方将校验和放在 UDP的校验和字段
接收方:
- 计算接收到的报文段的校验和
- 检查计算出的校验和与校验和字段的内容是否相等:
- 不相等––检测到差错
- 相等––没有检测到差错 ,但也许还是有差错
- 残存错误
可靠数据传输的原理
RDT1.0
在可靠信道上的可靠数据传输
- 下层的信道是完全可靠的
- 没有比特出错
- 没有分组丢失
- 发送方和接收方的FSM
- 发送方将数据发送到下层信道
- 接收方从下层信道接收数
RDT2.0
rdt2.0:具有比特差错的信道
- 下层信道可能会出错:将分组中的比特翻转
- 用校验和来检测比特差错
- 问题:怎样从差错中恢复:
- 确认(ACK):接收方显式地告诉发送方分组已被正确接收
- 否定确认( NAK): 接收方显式地告诉发送方分组发生了差错 ,发送方收到NAK后,发送方重传分组
- rdt2.0中的新机制:采用差错控制编码进行差错检测
- 发送方差错控制编码、缓存
- 接收方使用编码检错
- 接收方的反馈:控制报文(ACK,NAK):接收方发送方
- 发送方收到反馈相应的动作
RDT2.1
rdt2.1:发送方处理出错的ACK/NAK
发送方
:
- 在分组中加入序列号
- 两个序列号(0,1)就 足够了,一次只发送一个未经确认的分组
- 必须检测ACK/NAK是否 出错(需要EDC )
- 状态数变成了两倍,必须记住当前分组的序列 号为0还是1。
接收方
:
- 必须检测接收到的分组是否是重复的
- 状态会指示希望接收到的分组的序号为0还是1
注意:接收方并不知道发送方是否正确收到了其ACK/NAK,没有安排确认的确认。
RDT2.2
rdt2.2:无NAK的协议
- 功能同rdt2.1,但只使用ACK(ack 要编号)
- 接收方对最后正确接收的分组发ACK,以替代NAK,接收方必须显式地包含被正确接收分组的序号
- 当收到重复的ACK(如:再次收到ack0)时,发送方与收到NAK采取相同的动作:重传当前分组
- 为后面的一次发送多个数据单位做一个准备
- 一次能够发送多个
- 每一个的应答都有:ACK,NACK;麻烦
- 使用对前一个数据单位的ACK,代替本数据单位的NAK
- 确认信息减少一半,协议处理简单
RDT3.0
rdt3.0:具有比特差错和分组丢失的信道
新的假设:下层信道可 能会丢失分组(数据 或ACK)
- 会死锁
- 机制还不够处理这种状况:检验和,序列号,ACK,重传
方法: 发送方等待ACK一段合理的时间
- 发送端超时重传:如果到时没有 收到ACK->重传
问题:如果分组(或ACK )只是被延迟了:
-
重传将会导致数据重复,但利用序列号已经可以处理这个问题
-
接收方必须指明被正确接收的序列号
-
需要一个倒计数定时器
链路层的timeout时间是确定的,传输层timeout时间是适应式的。
流水线协议
流水线:允许发送方在未得到对方确认的情况下一次发送多个分组
-
必须增加序号的范围:用多个bit表示分组的序号
-
在发送方/接收方要有缓冲区
- 发送方缓冲:未得到确认,可能需要重传;
- 接收方缓存:上层用户取用数据的速率≠接收到的数据速率;接收到的数据可能乱序,排序交付(可靠)
滑动窗口(slide window)协议
发送缓冲区:
-
形式:内存中的一个区域,落入缓冲区的分组可以发送
-
功能:用于存放已发送,但是没有得到确认的分组
-
必要性:需要重发时可用
发送缓冲区的大小:一次最多可以发送多少个未经确认的分组
-
停止等待协议=1
-
流水线协议>1,合理的值,不能很大,链路利用率不能够超100%
发送缓冲区中的分组
-
未发送的:落入发送缓冲区的分组,可以连续发送出去;
-
已经发送出去的、等待对方确认的分组:发送缓冲区的分组只有得到确认才能删除
发送窗口:发送缓冲区内容的一个范围
- 那些已发送但是未经确认分组的序号构成的空间
发送窗口的最大值 <= 发送缓冲区的值
-
一开始:没有发送任何一个分组
- 后沿 = 前沿
- 之间为发送窗口的尺寸=0
-
每发送一个分组,前沿前移一个单位
接收窗口:
- 接收窗口 (receiving window)=接收缓冲区
- 接收窗口用于控制哪些分组可以接收;
- 只有收到的分组序号落入接收窗口内才允许接收
- 若序号在接收窗口之外,则丢弃;
- 接收窗口尺寸Wr=1,则只能顺序接收;
- 接收窗口尺寸Wr > 1 ,则可以乱序接收,但提交给上层的分组,要按序
- 接收窗口用于控制哪些分组可以接收;
例子:Wr=1,在0的位置;只有0号分组可以接收; 向前滑动一个,罩在1的位置,如果来了第2号分组,则丢弃。
接收窗口的滑动和发送确认
- 滑动:
- 低序号的分组到来,接收窗口移动;
- 高序号分组乱序到,缓存但不交付(因为要实现rdt,不允许失序),不滑动
- 发送确认:
- 接收窗口尺寸=1;发送连续收到的最大的分组确认(累计确认)
- 接收窗口尺寸>1;收到分组,发送那个分组的确认(非累计确认)
选择重传SR
-
接收方对每个正确接收的分组,分别发送 ACKn(非累积确认)
- 接收窗口>1,可以缓存乱序的分组
- 最终将分组按顺序交付给上层
-
发送方只对那些没有收到ACK的分组进行重 发-选择性重发
- 发送方为每个未确认的分组设定一个定时器
-
发送窗口的最大值(发送缓冲区)限制发送 未确认分组的个数
发送方:
从上层接收数据
:
- 如果下一个可用于该分组的序号可在发送窗口中,则发送
timeout(n)
:
- 重新发送分组n,重新设定定时器
ACK(n) in [sendbase,sendbase+N]:
-
将分组n标记为已接收
-
如n为最小未确认的分组序号,将base移到下一个未确认序号
接收方:
分组n [rcvbase, rcvbase+N-1]
-
发送ACK(n)
-
乱序:缓存
-
有序:该分组及以前缓存的 序号连续的分组交付给上层 ,然后将窗口移到下一个仍未被接收的分组
分组n [rcvbase-N, rcvbase-1]
- ACK(n)
其它
:
- 忽略该分组
GBN协议和SR协议的异同
- 相同之处
- 发送窗口>1
- 一次能够可发送多个未经确认的分组
- 不同之处
GBN
:接收窗口尺寸=1- 接收端:只能顺序接收
- 发送端:从表现来看,一旦一个 分组没有发成功,如:0,1,2,3,4 ; 假如1未成功,234都发送出去 了,要返回1再发送;GB1
SR
: 接收窗口尺寸>1- 接收端:可以乱序接收
- 发送端:发送0,1,2,3,4,一旦1 未成功,2,3,4,已发送,无需重发,选择性发送1
流水线协议:总结
Go-back-N:
-
发送端最多在流水线中有N个未确认的分组
-
接收端只是发送累计型确认cumulative ack
- 接收端如果发现gap,不确认新到来的分组
-
发送端拥有对最老的未确认分组的定时器
- 只需设置一个定时器
- 当定时器到时时,重传所有未确认分组
Selective Repeat:
-
发送端最多在流水线中有N个未确认的分组
-
接收方对每个到来的分组单独确认individual ack (非累计确认)
-
发送方为每个未确认的分组保持一个定时器
- 当超时定时器到时,只是重发到时的未确认分组
SW | ||
---|---|---|
SW = 1 | RW = 1 | S-W(停等协议) |
SW > 1 | RW = 1 | GBN(回退N步协议) |
SW > 1 | RW > 1 | SR(选择重传协议) |
面向连接的传输:TCP
TCP报文段结构
TCP 序号, 确认号
序号:
- 报文段首字节的在字节流的编号
确认号:
-
期望从另一方收到的下一个字节的序号
-
累积确认
TCP往返延时(RTT)和超时
E s t i m a t e d R T T = ( 1 − α ) × E s t i m a t e d R T T + α × S a m p l e R T T EstimatedRTT = (1- \alpha) \times EstimatedRTT + \alpha \times SampleRTT EstimatedRTT=(1−α)×EstimatedRTT+α×SampleRTT
- 指数加权移动平均
- 过去样本的影响呈指数衰减
- 推荐值: α = 0.125 \alpha = 0.125 α=0.125
设置超时
-
E s t i m t e d R T T EstimtedRTT EstimtedRTT + 安全边界时间
- E s t i m a t e d R T T EstimatedRTT EstimatedRTT 变化大 (方差大) ⇒ \Rightarrow ⇒ 较大的安全边界时间
-
S a m p l e R T T SampleRTT SampleRTT 会偏离 E s t i m a t e d R T T EstimatedRTT EstimatedRTT 多远:
D e v R T T = ( 1 − β ) × D e v R T T + β × ∣ S a m p l e R T T − E s t i m a t e d R T T ∣ DevRTT = (1-\beta)\times DevRTT + \beta \times |SampleRTT-EstimatedRTT| DevRTT=(1−β)×DevRTT+β×∣SampleRTT−EstimatedRTT∣
(推荐值: β = 0.25 \beta = 0.25 β=0.25)
超时时间间隔设置为:
T
i
m
e
o
u
t
I
n
t
e
r
v
a
l
=
E
s
t
i
m
a
t
e
d
R
T
T
+
4
×
D
e
v
R
T
T
TimeoutInterval = EstimatedRTT + 4 \times DevRTT
TimeoutInterval=EstimatedRTT+4×DevRTT
TCP:可靠数据传输
- TCP在IP不可靠服务的基础上 建立了rdt
-
管道化的报文段 • GBN or SR
-
累积确认(像GBN)
-
单个重传定时器(像GBN)
-
是否可以接受乱序的,没有规范
-
- 通过以下事件触发重传
- 超时(只重发那个最早的未确认段:SR)
- 重复的确认 (例子:收到了ACK50,之后又收到3 个ACK5)
TCP发送方事件
从应用层接收数据:
-
用 n e x t s e q nextseq nextseq 创建报文段
-
序号 n e x t s e q nextseq nextseq 为报文段首字节的字节流编号
-
如果还没有运行,启动定时器
- 定时器与最早未确认的报文段关联
- 过期间隔: T i m e O u t I n t e r v a l TimeOutInterval TimeOutInterval
超时:
-
重传后沿最老的报文段
-
重新启动定时器
收到确认:
- 如果是对尚未确认的报文段确认
- 更新已被确认的报文序号
- 如果当前还有未被确认的 报文段,重新启动定时器
接收方的事件 | TCP接收方动作 |
---|---|
所期望序号的报文段按序到达。 所有在期望序号之前的数据都 已经被确认 | 延迟的ACK。对另一个按序报文段的到达最 多等待500ms。如果下一个报文段在这个时 间间隔内没有到达,则发送一个ACK。 |
有期望序号的报文段到达。 另一个按序报文段等待发送ACK | 立即发送单个累积ACK,以确认两个按序报 文段。 |
比期望序号大的报文段乱序到达。 检测出数据流中的间隔 | 立即发送重复的ACK,指明下一个期待字节 的序号 |
能部分或完全填充接收数据间隔 的报文段到达。 | 若该报文段起始于间隔(gap)的低端, 则立即发送ACK。 |
快速重传
-
超时周期往往太长:
- 在重传丢失报文段之前的 延时太长
-
通过重复的ACK来检测 报文段丢失
-
发送方通常连续发送大量 报文段
-
如果报文段丢失,通常会 引起多个重复的ACK
-
-
如果发送方收到同一数据 的3个冗余ACK,重传最 小序号的段:
- 快速重传:在定时器过时 之前重发报文段
- 它假设跟在被确认的数据 后面的数据丢失了
- 第一个ACK是正常的;
- 收到第二个该段的ACK,表示接收方收到一个该段后的 乱序段;
- 收到第3,4个该段的ACK,表示接收方收到该段之后的2个 ,3个乱序段,可能性非常大段丢失了
TCP流量控制
- 接收方在其向发送方的TCP段 头部的
r
w
n
d
rwnd
rwnd 字段“通告”其空 闲
b
u
f
f
e
r
buffer
buffer 大小
- R c v B u f f e r RcvBuffer RcvBuffer 大小通过 s o c k e t socket socket 选项 设置 (典型默认大小为4096 字 节)
- 很多操作系统自动调整 R c v B u f f e r RcvBuffer RcvBuffer
- 发送方限制未确认(“ i n f l i g h t inflight inflight ”)字节的个数≤接收 方发送过来的 r w n d rwnd rwnd 值
- 保证接收方不会被淹没
TCP连接管理
TCP开始连接
在正式交换数据之前,发送方和接收方握手建立通信关系:
- 同意建立连接(每一方都知道对方愿意建立连接)
- 同意连接参数
TCP:关闭连接
客户端,服务器分别关闭它自己这一侧的连接,发送FIN bit = 1的TCP段
一旦接收到FIN,用ACK回应,接到FIN段,ACK可以和它自己发出的FIN段一起发送
可以处理同时的FIN交换
拥塞控制的原理
端到端拥塞控制:
-
没有来自网络的显式反馈
-
端系统根据延迟和丢失事件推断是否有拥塞
-
TCP采用的方法
网络辅助的拥塞控制:
- 路由器提供给端系统以反馈信息
- 单个bit置位,显示有拥塞 (SNA, DECbit, TCP/IP ECN, ATM)
- 显式提供发送端可以采用的速率
TCP拥塞
TCP拥塞控制:机制
端到端的拥塞控制机制
-
路由器不向主机有关拥塞的反馈信息
- 路由器的负担较轻
- 符合网络核心简单的 T C P / I P TCP/IP TCP/IP 架构原则
-
端系统根据自身得到的信息 ,判断是否发生拥塞,从而 采取动作
拥塞控制的几个问题
- 如何检测拥塞
- 轻微拥塞 (
收到有关某个段的3次重复ACK
) - 拥塞 (
某个段超时了(丢失事件)
)
- 轻微拥塞 (
- 控制策略
- 在拥塞发送时如何动作,降低速率
- 轻微拥塞,如何降低
- 拥塞时,如何降低
- 在拥塞缓解时如何动作,增加速率
- 在拥塞发送时如何动作,降低速率
TCP 拥塞控制:速率控制方法
如何控制发送端发送的速率
-
维持一个拥塞窗口的值: C o n g W i n CongWin CongWin
- 发送端限制已发送但是未确认的数据量(的上限): L a s t B y t e S e n t − L a s t B y t e A c k e d ≤ C o n g W i n LastByteSent-LastByteAcked \leq CongWin LastByteSent−LastByteAcked≤CongWin
-
从而粗略地控制发送方的往网络中注入的速率
-
C o n g W i n CongWin CongWin 是动态的,是感知到的网络拥塞程度的函数
- 超时或者3个重复
A
C
K
ACK
ACK,
C
o
n
g
W
i
n
CongWin
CongWin ↓
- 超时时: C o n g W i n CongWin CongWin 降为 1 M S S 1MSS 1MSS ,进入 S S SS SS 阶段然后再倍增到 C o n g W i n / 2 CongWin / 2 CongWin/2(每个RTT),从而进入 C A CA CA 阶段
- 3个重复 A C K ACK ACK : C o n g W i n CongWin CongWin 降为 C o n g W i n / 2 CongWin/2 CongWin/2 , C A CA CA 阶段
- 超时或者3个重复
A
C
K
ACK
ACK,
C
o
n
g
W
i
n
CongWin
CongWin ↓
-
否则(正常收到 ACK,没有发送以上情况): C o n g W i n CongWin CongWin 跃跃欲试↑
SS阶段
(慢启动):加倍增加(每个RTT)CA阶段
(拥塞避免):线性增加(每个RTT)
联合控制的方法:
- 发送端控制发送但是未确认的量同时也不能够超过接收窗口,满足流量控制要求
- S e n d W i n = m i n { C o n g W i n , R e c v W i n } SendWin=min \{ CongWin, RecvWin \} SendWin=min{CongWin,RecvWin}
- 同时满足拥塞控制和流量控制要求
TCP慢启动
-
连接刚建立, C o n g W i n = 1 M S S CongWin = 1 MSS CongWin=1MSS
- 如: M S S = 1460 b y t e s ⋀ R T T = 200 m s e c MSS = 1460bytes \bigwedge RTT = 200 msec MSS=1460bytes⋀RTT=200msec
- 初始速率 = 58.4 k b p s 58.4kbps 58.4kbps
-
可用带宽可能 >> MSS/RTT
- 应该尽快加速,到达希望的速率
-
当连接开始时,指数性增加发送速率,直到发生丢失的事件
- 启动初值很低 ,但是速度很快
-
当连接开始时,指数性增加(每个RTT)发送速率直到发生丢失事件
- 每一个RTT, CongWin加倍
- 每收到一个ACK时, CongWin加1
-
慢启动阶段:只要不超时或 3个重复ack,一个RTT, CongWin加倍
总结: 初始速率很慢,但是加速却是指数性的,指数增加,SS时间很短,长期来看可以忽略
TCP拥塞控制:AIMD
-
当收到3个重复的ACK时:
- CongWin减半
- 窗口(缓冲区大小)之后线性增长;
-
当超时事件发生时:
-
CongWin被设置成 1 MSS,进入SS阶段
-
之后窗口指数增长
-
增长到一个阈值(上次发生拥塞的窗口的一半)时 ,再线性增加
-
事件 | 状态 | TCP发送端行为 | 解释 |
---|---|---|---|
以前没有收到 ACK的data ,被ACKed | 慢启动 (SS) | CongWin = CongWin + MSS If (CongWin > Thres)状态变成 “CA” | 每一个RTT CongWin 加倍 |
以前没有收到 ACK的data 被ACKed | 拥塞避 免 (CA) | CongWin = CongWin+MSS * (MSS/CongWin) | 加性增加, 每一个RTT对 CongWin 加一个 1 MSS |
通过收到3个重 复的ACK,发现 丢失的事件 | SS or CA | Threshold = CongWin/2, CongWin = Threshold+3, 状态变成 “CA” | 快速重传, 实现乘性的减. CongWin 没有变成 1MSS |
超时 | SS or CA | Threshold = CongWin/2, CongWin = 1 MSS, 状态变成“SS” | 进入slow start |
重复的 ACK | SS or CA | 对被ACKed 的segment, 增加重复ACK的计数 | CongWin and Threshold 不变 |
TCP 公平性
公平性目标: 如果 K个TCP会话分享一个链路带宽为R的瓶颈,每一个会话的有效带宽为 R K \frac{R}{K} KR
2个竞争的TCP会话:
- 加性增加,斜率为1, 吞吐量增加
- 乘性减,吞吐量比例减少