计算机网络—自顶向下方法 传输层复习笔记
传输层
-
传输层协议为运行在不同主机上的应用进程之间提供了逻辑通信
-
传输层协议只运行于端系统中
传输层与网络层的关系
- 在协议栈结构中,传输层运行于网络层之上
- 传输层协议提供的服务部分 受制于网络层,如:
- 如底层网络层协议无法为报文提供时延和带宽保证,那么其上层传输层协议也做不到
- 但是即使底层网络层协议不可靠,不安全,运行于其上的传输层协议仍然可以做到可靠安全传输
因特网传输层概述
多路复用与多路分解
多路复用与多路分解是所有计算机网络都需要的
以下关于多路复用与多路分解的讨论均基于因特网技术
-
传输层并未直接将报文传递给进程,而是交给相应的中间[套接字](# 套接字)
-
多路分解:将传输层报文数据交付到正确套接字
-
多路复用:从源主机的各个套接字收集数据块,并为这些数据块封装传输层首部信息以生成报文段
然后将报文段传递给网络层
-
每个报文段都有一个特殊字段(源端口号和目的端口号)用于指示该报文段所要交付的套接字
套接字与端口号
-
每个套接字都能分配到一定端口号,一个套接字只能对应一个端口号,而一个端口号可以对应多个套接字
-
端口号:一个16比特数
- 周知端口号:0~1023范围内的端口号,使用受限,因其被保留用于一些周知的应用层协议使用
无连接传输:UDP
-
UDP仅在IP协议上增加了复用/分解和少量差错检测
-
UDP提供不可靠,无连接的服务
-
UDP协议使用无连接的多路复用与多路分解。通常,使用UDP的应用程序的客户端让传输层自动且透明的分配端口号,而服务器的则分配一个特定的端口号
-
UDP套接字由一个(目的IP地址,目的端口号)二元组标识,只要UDP报文的(目的IP地址,目的端口号)相同,报文就会被交付给相同的套接字,与(源IP地址,源端口号)无关
UDP的特点
-
无需连接建立:无连接建立时延(相比于TCP)
-
无连接状态
-
分组首部开销小:UDP首部:8字节 TCP首部:20字节
-
无拥塞控制:UDP可在网络处于重压状态下运行,但同时也有可能带来高丢包率并挤垮TCP会话
使用UDP的应用是可以实现可靠传输的(即使UDP是不可靠的),这需要应用在应用层或应用程序自身建立可靠机制
UDP报文结构
UDP首部长64比特(8字节),首部只要4个字段,每个字段长16比特(2字节)
-
源端口号,目的端口号:这两个字段是自解释的
-
长度:UDP报文段中的字节数(首部+应用数据)
-
检验和:接收方用于错误检测
UDP检验和
UDP检验和提供了差错检验概念,UDP检验和只能检测比特差错
UDP检验和的计算
发生方对UDP报文段中所有16比特字求和,求和过程中遇到的任何溢出都别回卷,对最后的和取反码,得到的最终结果就是UDP检验和
例:
假定有以下3个16比特字:
- 0110011001100000
- 0101010101010101
- 1000111100001100
- 第一个16比特字与第二个16比特字相加
- 将上面的和与第三个16比特字相加
- 由于出现溢出,所以进行回卷
-
对最后的和取反码,得到检验和
UDP检验和的性质
- UDP检验和检验出有错则一定有错
- UDP检验和没有检验出错误不一定无错
- UDP检验和只能检验错误,不能差错恢复
可靠数据传输原理
注意,下列讨论仅考虑单向数据传输,即数据传输是从发送端到接收端的。但双向数据传输的原理是相似的
构造可靠的数据传输协议
流水线可靠数据传输协议
信道利用率:发送方实际忙于将发送比特送进信道的那部分时间与发送时间之比
流水线:允许发送方发送多个分组而无需等待确认
若流水线长度为N,则最大信道利用率为:
U
s
e
n
d
e
r
=
(
N
L
)
/
R
R
T
T
+
L
/
R
U~sender~=\frac{(NL)/R}{RTT+L/R}
U sender =RTT+L/R(NL)/R
停等协议中,N=1
由于在流水线协议中,发送方可发送方发送多个分组。因此:
- 必须增加序号范围
- 协议的发送方和接收方要有缓存多个分组的能力
窗口与序号空间
-
基序号(base):最早未确认分组的序号
-
下一个序号(nextseqnum):最小未使用序号
-
窗口长度(window size):已被发送但还没被确认的分组的序号的许可范围。窗口长度是动态的。
注意:是许可范围,不是实际范围
-
序号空间:分组所能被分配到的所有可能序号所组成的数学空间。
-
如果分组序号字段的比特数为k,则序号范围为[0,2k-1]。
-
在有限的序号范围内,所涉及的所有序号运算最后必须进行一次模2k运算。即序号空间是一个长度为2k的环,其中
序号2k-1后紧接序号0
-
回退N步(GBN)
GBN发送方
GBN发送方窗口:
- 累积确认:若发送方收到对于序号为n的分组的确认,则认为接收方以成功正确接收序号为n及之前的所有分组
- 超时重发:如果出现超时,发送方将会重发所有已发送但未被确认的分组
GBN接收方
-
确认:接收方正确按序收到序号为n的分组,则向接收方为分组n发送一个ACK
-
分组失序:接收方丢弃所有失序分组
注意若接收方收到分组序号分别为:1、3、4、5,则分组3、4、5被视为失序分组,因为分组2未正确收到
-
累积确认:接收方每收到一个分组,就为最后正确按序接收的分组发送ACK
GBN运行示例
选择重传(SR)
- 选择重传(SR)仅需要重传丢失(包括超时)或受损的分组,无需重传失序分组
- 失序分组将被缓存在接收方缓存中,直到所有丢失分组(即序号更小的分组)都被收到为止
- 对于SR协议,窗口长度必须小于等于序号空间大小的一半
SR接收方与发送方的窗口和序号空间:
SR发送方
-
超时:每个分组都有一个自己的定时器,分组若发送超时则只重新发送超时分组
-
确认:收到分组ACK,若ACK分组序号在窗口内,SR发送方将该分组标记为已接收;若分组序号等于send_base(见上图)
则窗口基序号向前移动到具有最小序号的已发送未确认分组处
SR接收方
-
序号在 [ rcv_base,rcv_base+N-1 ] 内的分组被正确接收:
- 分组已被接收过:向接收方返回该分组ACK
- 分组未被接收过:向接收方返回分组ACK,缓存该分组。若分组序号等于rcv_base(见上图)
-
序号在 [rcv_base-N,rcv_base-1] 内的分组被正确接收:
分组之前已被正确接收,只需且必须向接收方返回该分组ACK
-
其余情况:分组被忽略
SR运行示例
可靠数据传输机制总结
-
检验和:检测分组中的比特错误
-
定时器:检测分组超时。超时可能有以下原因:
1. 分组或ACK丢失 2. 分组或ACK延时但未丢失
-
序号:为从发送方流向接收方的数据分组按顺序编号
-
确认:接收方用于告诉接收方一个或一组分组已正确收到。确认报文可携带多个分组序号
-
否定确认:接收方用于告诉接收方某个分组未被正确收到
面向连接的运输:TCP
-
TCP提供面向连接的,可靠的服务
-
TCP提供全双工服务
-
TCP仅提供点对点服务,多播对于TCP是不可能的
-
TCP协议使用面向连接的多路复用与多路分解。通常运行TCP协议的服务器有一个周知的欢迎套接字等待连接,连接完成后
会为客户生成一个新的套接字
-
TCP套接字由一个(源IP地址,源端口号,目的IP地址,目的端口号)四元组标识。服务器通过套接字标识中的源IP地址和
源端口号区分不同进程之间的报文段
TCP报文结构
TCP报文首部长一般是20字节
-
源端口号,目的端口号:各32比特,这两个字段是自解释的
-
序号:32比特,是该报文段首字节的字节流编号
- TCP将数据看做一个无结构,有序的字节流,因此序号是建立在字节流上,而不是报文段上
- 一个TCP报文段的序号就是该报文段首字节的字节流编号
- TCP连接双方均可随机选择起始序号。
-
确认号:32比特,TCP报文 发送方 期望从 接收方 收到的下一个字节的序号,TCP报文的ACK由此字段完成
-
首部长度:4比特,指示该TCP报文的首部长度(TCP报文的首部长度是可变的),单位为32比特字
-
6个标志字段:每个字段1比特
- RST、SYN、FIN:用于TCP连接的建立与拆除
- CWR、ECE:用于明确拥塞通告
- PSH:表示该数据应立即上交
- URG:报文段中存在“紧急”数据
-
接收窗口:16比特
-
因特网检验和:接收方用于错误检测
-
紧急数据指针:16比特,指出紧急接收的最后一个字节
-
选项:该字段是可选的,变长的。
往返时间的估计与超时
SampleRTT(样本RTT):从某个报文段被发出(交给IP)到该报文段的确认被收到之间的时间量
注意,TCP不为重传报文段计算SampleRTT
EstimatedRTT(典型RTT):SampleRTT的指数加权平均
E
s
t
i
m
t
e
d
R
T
T
=
(
1
−
α
)
⋅
E
s
t
i
m
t
e
d
R
T
T
+
α
⋅
S
a
m
p
l
e
R
T
T
EstimtedRTT=(1-\alpha)\cdot EstimtedRTT + \alpha \cdot SampleRTT
EstimtedRTT=(1−α)⋅EstimtedRTT+α⋅SampleRTT
一般取α=0.125
DevRTT(偏差RTT):用于估算SampleRTT偏离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) \cdot DevRTT + \beta \cdot | SampleRTT-EstimatedRTT |
DevRTT=(1−β)⋅DevRTT+β⋅∣SampleRTT−EstimatedRTT∣
β推荐值为0.25
超时间隔TimeoutInterval:超时间隔由EstimatedRTT和DevRTT共同决定
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 \cdot DevRTT
TimeoutInterval=EstimatedRTT+4⋅DevRTT
推荐初始TimeoutInterval为1秒。出现超时后TimeoutInterval将加倍。然而,只要收到新的报文段并更新EstimatedRTT,
TimeoutInterval就将重新计算
可靠数据传输
TCP的可靠数据传输服务确保一个进程从其接收缓存中读出的数据流是无损坏、无间隙、非冗余、按序的数据流
-
TCP协议仅使用单一的重传定时器,而非SR协议中为每个报文都设置一个定时器
-
超时:TCP通过重传超时的报文段相应超时事件,重传后TCP重启定时器
-
TCP采用选择确认:TCP接收方有选择的确认
-
TCP的每次重传都会导致下一次超时间隔加倍,正如[上文](# 往返时间的估计与超时)所讨论的一样
快速重传
TCP ACK的产生建议:
事件 | TCP接收方动作 |
---|---|
具有期望序号的按序报文到达,所有在期望序号及之前的数据都已被确认 | 延迟ACK,对另一个按序报文段的到达最多等待500ms。如果下一个报文段在这个时间内没有到达,则发送一个ACK |
具有期望序号的按序报文到达,但有另一个按序报文段等待ACK传输 | 立即发送单个累积ACK,以确认两个报文段 |
比期望序号大的报文段到达 | 立即发送冗余ACK,指示期望的下一个字节的序号 |
能部分或完全填充接收数据间隔的报文段到达 | 如果该报文段起始于间隔的低端,则立即发送ACK。否则,等同于上一种情况 |
冗余ACK:再次确认某个报文段的ACK,先前该报文段已被确认过
一旦收到3个冗余ACK,TCP就执行快速重传,即立刻发送丢失报文段(ACK中确认号期望的报文段),无论定时器是否过期
注意,执行快速重传时,发送方收到4个对同一报文段的ACK,1个正常ACK和3个冗余ACK
TCP的窗口协议
- TCP发送方仅需维持已发送的未被确认的最小序号和下一个要发送字节的序号
- TCP采用累积确认:即发送方收到对序号为n的确认,则认为接收方以正确接收序号为n及之前的分组
流量控制
流量控制服务:目的是防止发送方使接收方缓存溢出,其是一个速度匹配服务,即发送方发送速率与接收方应用程序的读取速率相匹配
TCP发送方维护一个接收窗口。(因为TCP是全双工协议,所以TCP连接双方都维护一个接收窗口)
TCP接收方为每个TCP连接维护一个接收缓存。
定义以下变量:
- RcvBuffer:接收缓存的大小
- rwnd:接收窗口大小
- LastByteRead: TCP接收方的应用进程从缓存中读出的字节流的最后一个字节的编号
- LastByteRcvd:从网络中到达并已被放入TCP接收方接收缓存的最后一个字节的编号
- LastByteSent: TCP发生方发送的字节流的最后一个字节的编号
- LastByteAcked: TCP发生方收到的已被确认的按序字节流的最后一个字节的编号
TCP不允许已分配的缓存溢出,即:
L
a
s
t
B
y
t
e
R
c
v
d
−
L
a
s
t
B
y
t
e
R
e
a
d
≤
R
c
v
B
u
f
f
e
r
LastByteRcvd - LastByteRead \leq RcvBuffer
LastByteRcvd−LastByteRead≤RcvBuffer
接收窗口大小(rwnd)是动态变化且与接收缓存相关的:
r
w
n
d
=
R
c
v
B
u
f
f
e
r
−
(
L
a
s
t
B
y
t
e
R
c
v
d
−
L
a
s
t
B
y
t
e
R
e
a
d
)
rwnd=RcvBuffer-(LastByteRcvd-LastByteRead)
rwnd=RcvBuffer−(LastByteRcvd−LastByteRead)
TCP发送方轮流跟踪 LastByteSent 和 LastByteAcked 两个变量。值得注意 LastByteSent - LastByteAcked 即为已发送但未被确认的数据量。TCP将未被确认的数据量控制在 rwnd 内,即要求:
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
≤
r
w
n
d
LastByteSent-LastByteAcked \leq rwnd
LastByteSent−LastByteAcked≤rwnd
接收缓存满时:
-
rwnd = 0,向发送方通告
-
TCP发送方收到 rwnd = 0 的通告后,继续发送只有**一个字节数据**的报文段,接收方将确认这些报文(确认报文中将包含接收方的
当前 rwnd 值)
TCP连接管理
TCP连接过程中的三次握手
-
客户端TCP向服务器端TCP发送一个SYN报文段
- SYN报文段:无应用层数据,标志字段中SYN比特置为1,序号字段由客户随机选择,该序号是本次TCP连接客户的初始序号(client_isn)
-
服务器的收到TCP SYN报文段,为该TCP连接分配TCP缓存和变量,并向客户回送SYNACK报文段
- SYNACK报文段:无应用层数据,标志字段中SYN比特置为1,序号字段由客户随机选择,该序号是本次TCP连接服务器的初始序号(server_isn),确认号字段为client_isn+1。此时TCP连接已经建立。
-
客户收到SYNACK报文段,为该TCP分配缓存和变量,并向服务器发送对SYNACK的确认报文。
- 该报文为一个普通报文,其标志字段中SYN比特为0,序号为client_isn+1,确认号为server_isn+1。注意,该报文可携带应用 层数据
TCP终止时的三次握手
与TCP连接时的三次握手类似,不过终止连接的特殊标志是FIN。
TCP连接过程中的状态变化
TCP客户端和服务器端的TCP状态变化是不完全相同的
客户TCP典型的状态变化序列:
服务器TCP典型的状态变化序列:
TCP中的拥塞控制
- 端到端拥塞控制:网络层没有为传输层拥塞控制提供显式支持。端系统必须通过对网络行为的观察来推断拥塞状况
- 网络辅助的拥塞控制:路由器向发送方提供有关网络拥塞状态的显式反馈信息。
- TCP使用端到端拥塞控制,因为IP不对拥塞控制提供显式反馈
TCP拥塞控制概述
-
发送方TCP跟踪一个额外变量:拥塞窗口 cwnd(congestion window)
-
发送方中已发送的未被确认的数据量小于等于cwnd与rwnd中的最小值
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 ≤ m i n { c w n d , r w n d } LastByteSent-LastByteAcked \leq min \{cwnd,rwnd\} LastByteSent−LastByteAcked≤min{cwnd,rwnd} -
TCP使用确认触发(或计时)增大拥塞窗口长度,即TCP是自计时的
-
拥塞窗口长度增大的速率与确认速率正相关
慢启动
-
cwnd初始值为 1 MSS
-
每当一个传输的报文段被首次确认,cwnd就增加 1 MSS。即慢启动状态,cwnd呈指数增长(1 -> 2 -> 4 -> 8 ->…)
注意cwnd增加,每次可传输的报文段数量就会增加,传输的报文段被首次确认的速率也会增加,进而导致cwnd
增加速率更快,产生指数增长。
-
慢启动的终止:
-
超时丢包:TCP将超时视为丢包,每当发生超时事件,慢启动终止,TCP将 ssthresh(慢启动阈值)设置为
cwnd / 2,随后将 cwnd 重置为 1 MSS 并重新开始慢启动
-
cwnd 等于或超过 ssthresh:慢启动终止,进入拥塞避免模式
-
冗余ACK:若检测到3个冗余ACK,慢启动终止,触发快速重传,并进入快速恢复模式
-
拥塞避免
- 线性增长:每个RTT只将 cwnd 增长 1 MSS (n -> n+1 -> n+2 -> …),即TCP发送方在此模式下无论何时收到一个新的确认,就z只将 cwnd 增加一个MSS字节。
- 拥塞避免的终止:
- 超时丢包:拥塞避免终止,TCP将 ssthresh(慢启动阈值)设置为cwnd / 2,随后将 cwnd 重置为 1 MSS 并开始慢启动
- 冗余ACK:若检测到3个冗余ACK,ssthresh置为 cwnd/2 ,cwnd = (cwnd/2) +3,拥塞避免终止,触发快速重传,并进入快速恢复模式
快速恢复(非必须)
- 每收到一个冗余ACK,cwnd 增加 1 MSS
- 快速恢复的终止:
- 丢失报文ACK到达:降低cwnd,进入拥塞避免模式
- 超时丢包:TCP将 ssthresh(慢启动阈值)设置为cwnd / 2,随后将 cwnd 重置为 1 MSS 并开始慢启动
总结回顾
TCP拥塞控制(即拥塞避免模式)是:每个RTT内 cwnd 线性(加性)增加 1 MSS,当出现3个冗余ACK事件后,cwnd 减半(乘性减)即加性增,乘性减(AIMD)