第三章 传输层
传输层服务与协议
传输层为两个不同主机上的应用程序之间提供逻辑通信机制
- 传输层协议运行在端系统
- 发送方: 将应用程序报文分成数据段传递给网络层,
- 接受方: 将数据段重新组装成报文传递到应用层
网络层为两个主机之间提供逻辑通信
主要提供两种协议TCP和UDP:
多路复用和多路分解
多路复用:从多个套接字收集数据,添加首部封装数据,然后将报文段传递到网络层的过程叫做多路复用
多路分解:将收到的数据传递到对应的套接字的过程叫做多路分解
- 如何工作?
- 主机收到IP数据报
- 每一个数据报有源IP目的IP
- 每一个数据报搬运一个数据段
- 每一个数据段有源和目标端口号
- 主机用IP地址和端口号指明数据段属于哪个合适的套接字
- 无连接多路分解:
- UDP套接字由两个因素指定(目的IP,目的端口号)
- 具有不同源IP/源端口号,但是具有相同目的IP和目的端口号的IP数据报,指向同样的套接字。
- 面向连接的多路分解
- TCP套接字由四部分指定:
- 源IP地址
- 源端口号
- 目的IP地址
- 目的端口号
- 接收主机使用所有的四个值将数据段定位到合适的套接字
- 服务器主机可同时支持很多个TCP套接字
- TCP套接字由四部分指定:
- 主机收到IP数据报
无连接传输:UDP
UDP套接字有两个属性标识(目的IP地址和目的端口号)
来自不同的IP地址/端口号的IP报文段可以导向同一个套接字
UDP具有以下特点:
- 不需要建立连接(代表延迟较低)
- 简单:在发送者与接受者之间不需要连接状态
- 报文首部很小
- 没有拥塞控制:UDP能够以尽可能快的速度传递
- UDP 使用尽最大努力交付,即不保证可靠交付,同时也不使用拥塞控制
- UDP是面向报文的传输协议,对于应用层的报文只添加首部信息就进行发送而不会对报文进行合并或者拆分
- 对于网络层交上来的UDP用户数据报,在去除首部后就原封不动的交付上层的应用程序
- 支持一对一、一对多、多对一、多对多的交互通信
数据段可能丢失、传递失序的报文到应用程序
无连接:在UDP接收者发送者之间没有握手、每个UDP数据段的处理独立于其他数据段
UDP的首部有八个字节,由四个字段组成,每个字段长度为两个字节,长度是指首部和数据的总长度
在UDP中在进行校验和的计算过程中,会引入UDP的伪首部,伪首部的作用仅仅是为了计算校验和
UDP校验和差错检测
目标:对传输的数据进行差错检测
- 发送方
- 将数据段看作16bit的整数序列
- 校验和:数据段内容相加(1的补码和,即反码)
- 发送者将校验和放入UDP的校验和域
- 接受方
- 计算接收到的数据段的校验和
- 检查计算的校验和是否等于校验和域中的值
Internet校验和
- 按位相加
- 回卷
- 取反
可靠数据传输原理
Rdt的发展
TCP套接字由四个属性表示(源IP地址,源端口号,目的IP地址,目的端口号)
- 逐步开发发送方和接收方的可靠数据传输协议 (rdt)
- 仅考虑单向数据传输,但控制信息将双向流动!
- 用有限状态机 (FSM) 来标示发送方和接收方
Rdt1.0 完全可靠信道上的可靠数据传输
- 在完美可靠的信道上
- 没有bit错误
- 没有分组丢失
- 发送方,接收方分离的 FSMs :
- 发送方发送数据到下层信道
- 接收方从下层信道接收数据
RDT2.0:具有bit错误的通道上的可靠数据传输
具有bit错误是指:在接收方接收的报文段中的数据可能会和发送方发送的数据不一致,一般通过差错校验机制来判断是否发送错误
- 如何从错误中恢复
- 确认(ACKs):接受方明确告诉发送方分组接收正确
- 否认(NAKs):接收方明确告诉发送方分组接收出错
- 发送方收到NAK后重发分组
- Rdt2.0新增差错检测和接收方反馈
- **缺陷:**ACK和NAK混淆
- 处理重复:发送方给每个分组加上序号【区分新旧分组】
- 在ACK/NAK混淆时发送方重发当前分组
- 接收方丢弃重复分组
- 只需要0、1信号就行,区分新老信号
什么是停等协议?发送方发送一个报文,然后等待接受方的响应
RDT2.1:发送方处理混乱的ACK/NAK
在2.0中,可能会出现发送的ACK/NAK出现错误因此出现了RDT2.1,通过分组上来添加序号来判断是否最新的分组
RDT2.2:无NAK的消息协议
不用 NAK, 如果上个报文接收正确接收方发送 ACK
接收方必须明确包含被确认的报文的序号
发送方收到重复 ACK 将导致和 NAK一样的处理: 重发当前报文
在2.1中可以去掉NAK,只通过ACK来表示可以减少信息类型数量
RDT3.0:具有出错与丢失的信道
发送的消息除了出错之外,还有可能完全丢失,需要设置定时器当超过一定时间后重新发发送分组
a)正常发送
b)一号报文丢失
d)发送方超时间隔过短
定量看:rdt3.0的性能
例如: 1 Gbps链路, 15 ms 端到端传输延迟, 8000bit 报文, 计算网络利用率?
停等浪费了物理资源的使用
流水线技术
- 流水线:允许发送方可以在接收到ACK之前发送其他分组
- 序号数目的范围必须增加
- 在发送方/接收方必须有缓冲区
- 两个通用形式
- go-Back-N
- 选择重传
Go-Back-N【滑动窗口协议】
发送方:
-
在分组头中规定一个k位的序号【0-2k-1】
-
“窗口”, 允许的连续未确认的报文【长度为n的序列】
-
ACK(n): 确认所有的报文直到(包含)序号n - “累积ACK”
-
对第一个发送未被确认的报文定时
-
超时(n): 重发窗口中的报文n及以上更高序号的报文(只有一个定时记录最早的未被确认报文的发送时间)【窗口下沿设置定时器】
接收方
重发最高序号的分组ACK
- 发送0-3号报文后,等待ACK
- 0和1号ACK到了,窗口移动到2号,并发送4和5号
- 由于二号报文丢失了,于是接收方丢弃345,并且都回复ACK1,要求传二号报文
- 发送方的二号报文窗口下沿超时,重发2345报文
4567
收到了023的ACK,接收方发送的ACK是按序列顺序进行发送的,说明1号分组发送成功,只是ACK1丢失。所以需要重传最大的ACK+1的分组及其后面的分组
选择性重传SR
- 接收方分别确认已经收到的分组
必要时,缓冲报文, 最后按序提交给上层 - 发送者只重发没有收到确认的分组
对每个没有确认的报文发送者都要启动一个定时器(每个未被确认的报文都有一个定时器) - 发送窗口
N 个连续序号
限制被发送的未确认的分组数量
和GBN的区别,发送方的窗口出现间隙
发送方接收方的窗口不一致
发送方收到ACK时,若在窗口范围内,标注为被接收,如果接收后使得窗口某一部分被填满了,则窗口向右边滑动
接收方如果接收分组在窗口内,就发送ACK
失序分组暂时缓存
有序分组:交付上层,窗口滑动
接收方收到窗口左边的分组,必须发送相应的ACK,否则发送方的窗口会被卡住
二号在传输过程中丢失了,接收方缓存345
发送方因为超时重传二号包
序号是有限的,窗口大小小于或等于序号空间大小的一半
面向连接传输TCP
报文段结构
新版的首部格式:
CWR:CWR 标志与后面的 ECE 标志都用于 IP 首部的 ECN 字段,ECE 标志为 1 时,则通知对方已将拥塞窗口缩小;
ECE:若其值为 1 则会通知对方,从对方到这边的网络有阻塞。在收到数据包的 IP 首部中 ECN 为 1 时将 TCP 首部中的 ECE 设为 1.;
URG:该位设为 1,表示包中有需要紧急处理的数据,对于需要紧急处理的数据,与后面的紧急指针有关;
ACK:该位设为 1,确认应答的字段有效,TCP规定除了最初建立连接时的 SYN 包之外该位必须设为1;
PSH:该位设为 1,表示需要将收到的数据立刻传给上层应用协议,若设为 0,则先将数据进行缓存;
RST:该位设为 1,表示 TCP 连接出现异常必须强制断开连接;
SYN:用于建立连接,该位设为 1,表示希望建立连接,并在其序列号的字段进行序列号初值设定;
FIN:该位设为 1,表示今后不再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换 FIN 位置为 1 的 TCP 段。每个主机又对对方的 FIN 包进行确认应答之后可以断开连接。不过,主机收到 FIN 设置为 1 的 TCP 段之后不必马上回复一个 FIN 包,而是可以等到缓冲区中的所有数据都因为已成功发送而被自动删除之后再发 FIN 包;
TCP序号和确认
- 序号:
- 数据段中第一个字节在数据流中的位置编号
- 确认:
- 期望从另外一边收到的下一个字节的序号
- 累计ACK
问: 接收方如何处理失序的数据段
答: TCP规范没有明确规定, 由编程人员处理
TCP往返时延的估计和超时
如何设置 TCP 超时值?
比 RTT长;但 RTT变化
太短: 不成熟的超时、不必要的重传
太长: 对数据段丢失响应慢
首先指定RTT的初始估计值
每次接收到样本RTT,和预测RTT指数加权平均
TCP可靠数据传输机制
-
TCP在IP不可靠服务之上创建rdt服务
-
流水线技术处理报文段
-
累积确认
-
GBN和选择性重传的综合
-
TCP不会像GBN一样直接将失序报文报文丢掉,而是像SR一样缓存。
发送方不会重传一大段报文,只重传没有被确认的
TCP使用累计确认,为了降低开销只使用单个重发定时器,和GBN类似
-
-
TCP 使用单个重发定时器
-
触发重发:
——超时事件
——重复确认
快速重传
超时触发重传存在问题:超时周期往往太长
重传丢失报文之前要等待很长时间,因此增加了网络的时延
- 发送方可以在超时之前通过重复的ACK检测丢失报文段
- 发送方常常一个接一个地发送很多报文段
- 如果报文段丢失,则发送方将可能接收到很多重复的 ACKs
- 如果发送方收到一个确认后再收到3个对同样报文段的确认,发送方应意识到不对劲——生成三个重复ACK,是因为接收方存在缺失报文段【冗余ACK】
- 启动快速重传: 在定时器超时之前重发丢失的报文段
接收方收到乱序的包就会发送重复ACK,两次的重复ACK可能是重新排序造成的,三次的重复ACK可能是丢包造成的
两次重复ACK肯定是乱序造成的
丢包肯定会造成三次重复ACK
假定通信双方如下,A发送4个TCP 报文段给B,编号如下,N-1成功到达,因此A收到B的ACK(N),重组到达顺序,观察收到ACK(N)的数量
A 发送至 B
A方发送顺序->N-1,N,N+1,N+2
B方到达顺序
由于累计确认机制,如果发生乱序
① N-1,N,N+1,N+2 -> A收到1个ACK (N)
② N-1,N,N+2,N+1 -> A收到1个ACK (N)
③ N-1,N+1,N,N+2 -> A收到2个ACK (N)
④ N-1,N+1,N+2,N -> A收到3个ACK (N)
⑤ N-1,N+2,N,N+1 -> A收到2个ACK (N)
⑥ N-1,N+2,N+1,N -> A收到3个ACK (N)
如果N丢包
N-1,N+1,N+2 -> A收到3个ACK (N)
N-1,N+2,N+1 -> A收到3个ACK (N)
TCP 乱序 有2/6 的概率会造成A收到三次冗余ACK(N);
而如果N丢了,则概率为100%A
基于以上的统计,当A接收到三次 冗余ACK(N)启动立马快速重传N可快速修复一个丢包的恶劣影响。
而如果A接收到二次冗余ACK(N),则说明是乱序造成的,已经传送到了B
图自小林coding
在上图,发送方发出了 1,2,3,4,5 份数据:
- 第一份 Seq1 先送到了,于是就 Ack 回 2;
- 结果 Seq2 因为某些原因没收到,Seq3 到达了,于是还是 Ack 回 2;
- 后面的 Seq4 和 Seq5 都到了,但还是 Ack 回 2,因为 Seq2 还是没有收到;
- 发送端收到了三个 Ack = 2 的确认,知道了 Seq2 还没有收到,就会在定时器过期之前,重传丢失的 Seq2。
- 最后,收到了 Seq2,此时因为 Seq3,Seq4,Seq5 都收到了,于是 Ack 回 6 。
所以,快速重传的工作方式是当收到三个相同的 ACK 报文时,会在定时器过期之前,重传丢失的报文段。
流量控制
TCP连接的接收方有一个接收缓冲区:应用程序可能从这个缓冲区读出数据很慢
- 提供速度匹配服务
- 发送速率和接受应用程序提取速率匹配
- 流量控制
- 发送方不能发送的太多太快,让接收缓冲区溢出
(假设 TCP 接收方丢弃失序的报文段)
- 流量控制使用接收窗口【窗口字段】:接收缓冲区的剩余空间
- 接收方在报文段中宣告接收窗口的剩余空间
- 发送方限制没有确认的数据不超过接收窗口
- -保证接收缓冲区不溢出
- 接收方控制发送方
连接管理
连接:通信双方通信之前确认彼此的存在,确认一些通信需要的参数,做好一些资源的准备,如开辟缓冲区等。通信过程中需要维护连接状态的存在,当结束通信时通过合理的步骤逐步终止通信过程释放资源。
- 客户端发送不带数据的、SYN标志位为1、指定客户端随机初始序号的数据报请求连接建立
- 服务器接收,回复ACK=1、SYN=1、指定服务器的随机初始序号
- 客户端接收,回复ACK=1、SYN=0,可携带数据
为什么是三次握手?
为什么不是两次
- 三次握手双方都要对信道的可靠性做至少一次确认
- 服务器和客户端都要对双方选择的初始序号进行确认,这样双方才能使用该序号+1来发送数据
- 信道不可靠, 但是通信双方要要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足"在不可靠信道上可靠地传输信息"这一需求所导致的
为什么不选择更多次
- 下层信道是不可靠的,无法完全保证连接建立好了
- 从效率出发,保证三次即可
假设发送方和接收方为ab
其实很简单, 1.a->b, 这个时候没有任何状态, 2. b->a, b给a发东西, 说明收到了a的东西, 证明了a的发送能力是没问题的,同时证明了b的接收能力也是没有问题的。 如果到这里就结束了, 那么a的接收能力和b的发送能力就没办法保证了。如果再加上3. a->b , 证明了a收到了b的发送, 那么b的发送能力也是好的, a的接收能力也是好的。这样a和b的接收发送的能力都是好的, 就没必要再次证明了
关闭是双向的
拥塞控制原理
多个终端发送数据的时候由于链路带宽的限制若发送过多数据会导致分组丢失和排队时延较长,为了解决这个问题TCP引入了拥塞控制
- 丢失分组:路由器的缓冲区溢出
- 长延迟:路由器的缓冲区排队
流量控制:不让接收方来不及接收报文【发送方不会淹没接收方】
拥塞考虑的是网络的情况
- 端到端拥塞控制
- 没有从网络中得到明确的反馈
- 从端系统观察到的丢失和延迟推断出拥塞
- TCP采用的方法
- 网络辅助的拥塞控制
- 路由器给端系统提供反馈【路由器协助】
- 单bit指示拥塞 (SNA, DECnet, TCP/IP ECN, ATM)
- 指明发送者应该发送的速率
发送方通过调整发送行为来对拥塞进行反应,发送速率是通过调整发送窗口的大小实现的
流量控制中发送方的窗口大小是由接收方返回的接收窗口字段进行调整
引入新机制:拥塞窗口【CongWin】,发送窗口=min{拥塞窗口,接收窗口}
TCP拥塞控制的重点就是通过对网络的感知动态的调整拥塞窗口
发送方通过丢包事件感知拥塞->超时、三次冗余ACK
TCP发送方在丢失事件后降低发送速率【减小拥塞窗口】
采用三个机制
- 慢启动
- 对拥塞事件做出反应
- AIMD【加性增,乘性减】
慢启动
- 刚启动时,将拥塞窗口设为一个最大报文段
- TCP以2的指数方式增加速率直到产生丢失事件,或者达到某个阈值ssthresh
每个RTT中拥塞窗口翻倍
- 超时事件
- 拥塞窗口置为1MSS,进入慢启动,到达阈值线性增长
- 三次冗余ACK
- 拥塞窗口减半 + 3,然后线性增长
- 表明网络有传输的能力
- 最初是指定的
- 随着传输的进行动态变化,设为丢包之前的一半
AIMD【加性增乘性减】
- 发生丢包事件:拥塞窗口减半
- 每个RTT拥塞窗口增加一个MSS
慢启动状态:拥塞窗口呈2的指数倍增长
拥塞避免状态:拥塞窗口线性增长快速恢复状态:每收到一个重复的ACK,拥塞窗口+1【网络数据包守恒原则】
无论何种状态,超时事件发生则转移到慢启动状态,阈值降为丢包前窗口的一半,拥塞窗口变为1;
无论何种状况,收到3个重复的ACK,转移到快速恢复状态,阈值降为丢包前的一半,拥塞窗口变为新阈值+3
拥塞窗口到达阈值就变为拥塞避免状态
快速恢复状态收到新的ACK转移到拥塞避免状态,并且将拥塞窗口设为阈值
TCP 平均吞吐量
假设忽略慢启动
假设在丢失发生时,设W是窗口大小
如果窗口为 W, 吞吐量是 W/RTT
丢失发生后, 窗口降为 W/2, 吞吐量为 W/2RTT.
平均吞吐量为0 .75 W/RTT
第三章作业
10
以太网帧的数据段的最大长度为1500 byte
1500 byte 减去 IP数据报的首部20 byte,IP片的数据长度最大为1500 - 20 = 1480 byte
IP的数据段 为 UDP报文端 : 8(UDP首部) + 8192 = 8200 byte
8200 / 1480 = 5 … 800 所以应该划分 6 个IP数据报片
对于IP片偏移,其单位为8 byte 需要除以8,如下: