传输层服务
提供逻辑通信,传输层运行在端系统
网络层:主机之间逻辑通信
传输层:进程之间逻辑通信 可靠,增强网络层服务
Internet传输层协议
TCP、UDP("尽力传递"IP的直接拓展):将两个端系统间IP的交付服务拓展为运行在端系统上两个进程之间的交付服务
多路复用和多路分解
- 在接收主机多路分解:运输层报文段中的数据交付到正确的套接字
- 在发送主机多路复用:在源主机从不同套接字中收集数据块,并为每个数据块封装上首部信息(这将在以后用于分解)从而生成报文段,然后将报文段传递到网络层
多路分解工作原理:主机用IP地址和端口号指明数据段属于哪个合适的套接字
无连接多路分解
- 用端口号创建套接字
- 当主机收到UDP数据段:
- 检查数据段中的目的端口号
- 用端口号指示UDP数据段属于哪个套接字
- 具有不同的源IP地址且/或源端口号,但具有相同的目的IP地址和目的端口号的IP数据报,指向同样的套接字
- 请求报文段中提供返回地址(包括IP地址和端口号)
面向连接多路分解
大量数据成帧,查看帧头,解封装,返回IP Packet,然后再解封转,返回segment
用源IP地址、源端口号、目的IP地址、目的端口号定位合适的套接字
UDP
特点:
- 不需要建立连接(没有握手)——减少延迟
- 简单:在收发之间不需要连接状态
- 很小的数据报头,首部只有8字节,每个字段2字节
- 没有拥塞控制:UDP能尽可能快的速度传递
- UDP面向报文
- 添加首部后向下交付给IP层,去除首部交付上层的应用程序
- UDP不会合并或拆分报文,一次就发送一个报文
长度:首部和数据的总长度
校验和:用于差错检测,计算时,会临时把伪首部和UDP用户数据报连接在一起
其中第三个字段用于填充对其
第四个字段表示协议类型:TCP-6,ICMP-58,UDP-17,此处是UDP协议,所以是17
校验和算法
- 计算checksum的数据每16bit划分为一段,如果最后有单个字节的数据,补一字节的0组成两字节
- 每个段累加到32bit上(求和时产生的进位回卷加到末位)
- 32bit再划分为两个16bit累加求和
- 取反(之所以取反是为了方便检验时计算出来的checksum和传过来的checksum相加为全1,然后再取反为0)
差错检测不能完全保证正确性,总会有错误
可靠数据传输(必考)
RDT:reliable data transfer
UDT:unreliable data transfer
上层调用rdt_send()将数据传送到下一层,接收应用层发送过来的数据
应用层 传输层 网络层之间
有限状态机(FSM):来标识发送方和接收方
逐步开发发送方和接收方的可靠的数据传输协议(rdt), 仅考虑单项数据传输但控制信息将双向流动
- unforced state:
- forced state:不会停留
基本框架
红线以上是网络应用层;红线下是不可靠信道,抽象的概念,把下层整合
RDT1.0
假设在完全可靠的信道上: 没有bit错误,没有分组丢失
发送方,接收方分离的FSMs: 发送方发送数据到下层信道; 接收方从下层信道接收数据
RDT2.0 具有bit错误的信道
应对方法: 检验和将检测到bit错误
增加机制:
- 差错检验
- 接收方反馈:控制信息(ACK确认; NAK否认,需要重发) rcvr->sender
在接收端因为不需要等待且和现有的状态不同,都只是在等下层的调用,所以也不用增加别的状态
如果传送多个数据包时,是一次发送完后再进等待,还是发一个等待一个?
发一个等一次回复
缺点:ACK和NAK会受损(信道不可靠),出现多重包
解决方法:增加编号,丢掉重复编号的包
rdt2.1:处理损坏的ACK/NAKs
发送方
序号的作用
为什么要判断两遍,判断是否损坏和NAK 然后又判断是ACK 损坏?
在2.1改进了
损坏和NAK都要重发.
如果接收端正常接收, 但是发送方无法识别包,所以会重发包.
既没有损坏也不是NAK,就是ACK进入等待上层调用1
为什么用0,1就可以
接收方
接收端收到的包如果序号不一样,可以判断出是重发了
就算判断出是重发了还是会返回ACK,只要这个包是正常的,都是会发送出ACK,感觉没什么作用?
rdt2.2:不再使用NAK
给ACK带上序号,就不需要再使用NAK
收到ACK1的原因: 接收端在等待0的状态下收到序号1的包,则返回ACK1–>那就是发送端发送了pkt1–>
发送端在发送pkt0的时候发生错误,接收端接收到损坏的pkt,就返回了ACK1
左下方出现seq1: 接收端接收到pkt1–>发送端发送了pkt1–>本应该发送pkt0但是发送了pkt1说明发生了重传–>发送端处于等待ACK0
rdt3.0 :出错且会丢包
方法:发送方等待一段时间
timer: 对方没有收到包; 网络延迟大;回复的报文丢失
为什么不在等待ACK0收到ACK1的时候做操作?
因为要将time清零,会增加复杂度.可以,但是不好. 在premature timeout避免无限重传
常见情况对应的收发端操作
性能分析
停等操作
传输时延:t=L/R
传播时延:RTT(一组传播时延、排队时延等)
T
t
r
a
n
s
m
i
t
=
L
/
R
=
8
m
s
U
s
e
n
d
e
r
=
L
/
R
R
T
T
+
L
/
R
=
0.00027
T_{transmit}=L/R=8ms U_{sender}=\frac{L/R}{RTT+L/R}=0.00027
Ttransmit=L/R=8msUsender=RTT+L/RL/R=0.00027
改进
流水线技术:发送方允许发送多个“在路上的”还没确认的报文,
- 序号的数目范围必须增加
- 在发送方/接收方必须有缓冲区
Go-Back-N
发送方:在分组头中规定一个k位的序号 ; "窗口"允许的未确认的报文
接收到一个ACK后窗口向后滑动
ACK(n)
:确认所有的报文直到(包含)序号n - “累积ACK”对第一个发送未被确认的报文定时
超时(n)
:重发窗口中的报文n及以上更高序号的报文(只有一个定时器记录最早的未被确认报文的发送时间)
sand_base
:窗口中已经发送的具有最小序号的报文
nextseqnum
:可发送还未发送的报文
FSM
之所以只是用一个状态,最关键原因:因为有太多序号
接收方:总是位正确接收的最高序号的分组发送ACK
- 可能生成重复的ACKs
- 只记住被期待接收的序号
接收到失序分组:丢弃(不缓冲),没有接收缓冲区,重发最高序号分组的ACK
FSM
wait的原因: 将窗口大小设为了4
第一次rcv pkt3返回ACK1:
因为pkt2丢失,导致接收到的分组时序,pkt1之前是正确的,所以2出问题,2之后的重发
选择性重传(Selective Repeat,SR)
基本思想
- 接收方分别确认已经收到的分组(缓冲)
- 发送者只重发没有收到确认的报文
- 发送窗口:连续n个序号; 限制被发送的未确认的分组数量
模型
分析上图的对应关系产生情况
rcv_base前四个已经正常接收到pkt了,并且返回了ACK,但是send_base后两个是没有接收到ACK
发送端
- 从上层接收数据
- 超时(n):重发分组n,并重启计时器
- 收到ACK(n):标记分组n被接收; 如果n是最小的未确认分组,则窗口后移一格(窗口第一位为n,接收到ACKn,后移一位)
接收端(为什么又两个范围?)
- 分组n的序号在[rcvbase, rcvbase+N-1]内
- 发送ACK(n)
- 失序分组: 缓冲
- 有序分组: 交付上层 (包括已经缓冲的有序分组), 提高窗口到下一个没有接收的分组
- 分组n在[rcvbase-N,rcvbase-1]内
- 发送ACK(n)
例子
存在两难困境
窗口需小于或等于序号空间大小的一般
TCP
特点:
- 点到点
- 可靠按序的字节流
- 流水线
- 收发缓冲区
- 全双工1数据:
- 面向连接
- 流量控制
报文段的首部格式
序号:数据段中第一个字节在数据流中的位置编号
确认号:期望从另外一边收到的下一个字节的序号
SYN:用于三次握手
ACK:累计ACK
窗口:window size 用于流控
校验和:要加上伪首部
TCP超时
要设置TCP的超时,必须要大于RTT,但是RTT变化
太短:不必要的重传
太长:对数据段丢失相应慢
估计RTT
样本RTT:测量从报文发送到接收到确认的时间——忽略重传
RTT均值(Estimated RTT)
→
\rightarrow
→
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
Estimated RTT =(1- α)*Estimated RTT + α*Sample RTT
EstimatedRTT=(1−α)∗EstimatedRTT+α∗SampleRTT
典型的α=0.125
最开始会发送一个测试包,获得样本RTT
虽然可用,但是大部分还是难以覆盖
需要增加一个"安全余量"
D
e
v
R
T
T
=
(
1
−
b
)
×
D
e
v
R
T
T
+
b
×
∣
S
a
m
p
l
e
R
T
T
−
E
s
t
i
m
a
t
e
d
R
T
T
∣
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
DevRTT = (1-b) \times DevRTT +b \times |SampleRTT-EstimatedRTT|\\TimeoutInterval = EstimatedRTT + 4*DevRTT
DevRTT=(1−b)×DevRTT+b×∣SampleRTT−EstimatedRTT∣TimeoutInterval=EstimatedRTT+4∗DevRTT
可靠数据传输
特点:
- TCP在IP不可靠服务之上创建rdt服务
- 流水线技术处理报文段
- 累积确认
- TCP 使用单个重发定时器
- 触发重发:
- 超时事件
- 重复确认
发送方事件
- 从应用程序接收数据
- 用序号创造一个数据段
- 序号是数据段中第一个数据字节在字节流中的位置编号
- 如果没有启动定时器,则启动定时器
- 定时器是最早没有被确认的数据段发送时启动的
- 设置超时间隔: TimeOutInterval
- 超时
- 重发导致超时的数据段
- 重新开始定时器
- 收到确认
- 如果确认了还没有确认的数据段
- 更新还没有确认的状态
- 还有未完成的数据段,重新开始定时器
序号逻辑
sendbase -1 =上一次ack的ack的字节
TCP会缓存乱序的报文
重传的场景
快速重传(在累积ACK上优化)
在timeout之前,当发现有重复(一般是3个)的ACK收到时
流量控制
速度匹配服务:发送速率和接收应用程序的提取速率减半
流量控制:发送方不能发送的太多太快,让接收缓冲区溢出
TCP连接的接收方有一个接收缓冲区,应用程序可能从缓冲区读出数据很慢
- 实现方法
- 滑动窗口协议(连续ARQ协议):接收方返回的ACK中回包含自己的接收窗口的大小
数据写入顺序:从低位地址开始写
连接管理
建立连接两次握手不行吗?
建立连接的三次握手
关闭连接的四次握手
为什么建立连接是三次握手,断开连接是四次握手
建立连接本质上也是四次握手,接收双方要相互确认连接是否建立成功,但是中间两次可以合并成一次,即确认和请求同一次传输
因为连接时,调用socket的connect函数发送SYN包,而服务器端只是accept一下,就一次发送了SYN和ACK标志位,而到了断开连接时大家都要调用各自的close函数结束这段socket,所以两次close分别触发了两次FIN包,导致没有和ACK合并为一个包,所以握手3次,分手要4次。
因为发送方发送完数据包后,需要等待接收端处理完数据、发送完数据,即接收端也没有数据需要发送的时候
TCP FSM
拥塞控制
拥塞产生原因
- 太多源主机发送太多数据,速度太快,以至于网络来不及处理
- 表现
- 丢失分组(路由器的缓冲区溢出)
- 长延迟(在路由器的缓冲区排队)
场景
- 单个路由器,缓冲区无限
- 单个路由器,缓冲区有限
- 时延过长,导致终端重发,使拥塞更加严重
- 多个路由器
- 当分组丢失后,任何上游路由器的发送能力都浪费了
拥塞控制方法
- 端到端拥塞控制(TCP采用的方法)
- 没有从网络中得到明确的反馈
- 从端系统观察到的丢失和延迟推断出拥塞
- 网络辅助的拥塞控制
- 路由器给端系统提供反馈
- 指明发送者应该发送的速率
- 单bit指示拥塞(SNA, DECbit,TCP/IP ECN, ATM)
具体方法
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
o
n
g
W
i
n
,
R
c
v
W
i
n
)
大
体
上
:
r
a
t
e
=
C
o
n
g
W
i
n
R
T
T
B
y
t
e
s
/
s
e
c
LastByteSent -LastByteACKed < min(CongWin, RcvWin)\\ 大体上:rate = \frac{CongWin}{RTT} Bytes/sec
LastByteSent−LastByteACKed<min(CongWin,RcvWin)大体上:rate=RTTCongWinBytes/sec
CongWin(拥塞窗口,congestion window) : 最大可连续发送的数量(发送窗口大小)
通过丢包来感知拥塞:TCP发送方在丢失事件发生后降低发送速率
机制
- 慢启动(slow start)
- 开始连接时 CongWin = 1 MSS
- 有效带宽将 >> MSS/RTT : 以2的指数方式增加速率知道产生丢失事件或达到阈值
- 对拥塞事件作出反应
- 当超时事件发生时
- CongWin立即设置为1个MSS
- 窗口开始指数增长(进入慢启动),达到阈值(阈值也会下降)后再线性增长
- 连续收到三个重复确认
- CongWin 减半+3 (Reno版) ,然后开始线性增长
- 当超时事件发生时
- AIMD(Additive Increase Multiplicative Decrease)
- 乘性递减:发生丢包事件后将拥塞窗口减半
- 加性递增:每个RTT内如果没有丢失事件发生,拥塞窗口增加一个MSS
新ssthresh值:24/2=12
重视FSM的绘制
TCP拥塞控制的FSM图
TCP平均吞吐量
忽略慢启动,假设丢失发生时窗口大小为
W
W
W,则吞吐量为
W
R
T
T
\frac{W}{RTT}
RTTW,丢失发生后,窗口下降为
W
/
2
W/2
W/2,吞吐量为
W
2
R
T
T
\frac{W}{2RTT}
2RTTW,则平均吞吐量为
0.75
W
/
R
T
T
0.75W/RTT
0.75W/RTT
TCP公平
- 目标:K个TCP共享R宽带,每个应有R/K的平均速率
- 丢失:减小窗口 ; 拥塞避免:增加窗口
同一时间点能收也能发;对讲机是半双工,同一时间一个机子只能接收或发送 ↩︎