第三章:传输层
概述和传输层服务
传输服务和协议
-
为运行在不同主机上的应用进程提供逻辑通信
-
传输协议运行在端系统
-
发送方:将应用层的报文分成报文段,然后传递给网络层
-
接收方:将报文段重组成报文,然后传递给应用层
-
-
有多个传输层协议可供应用选择
-
TCP
-
UDP
-
传输层 vs. 网络层
网络层服务:主机之间的逻辑通信
传输层服务:进程间的逻辑通信
-
依赖于网络层的服务
-
并对网络层的服务进行增强,可增强的服务:不可靠->可靠,安全,不可被增强,带宽,延迟
Internet传输层协议
-
可靠的、报序的传输:TCP
-
多路复用,解复用
-
拥塞控制
-
流量控制
-
建立连接
-
-
不可靠、不保序的传输:UDP
-
多路复用、解复用
-
没有为尽力而为的IP服务添加更多的额外服务
-
-
都不提供的服务:
-
延时保证
-
带宽保证
-
多路复用与解复用
在发送方主机多路复用
从多个套接字接收来自多个进程的报文,根据套接字对应的IP地址和端口号等信息对报文段用头部加以封装 (该头部信息用于以后的解复用
在接收方主机多路解复用
根据报文段的头部信息中的IP地址和端口号将接收到的报文段发给正确的套接字(和对应的应用进程)
多路解复用的工作原理
-
解复用作用:TCP或者UDP实体采用哪些信息,将报文段的数据部分交给正确的socket,从而交给正确的进程
-
主机收到IP数据报
-
每个数据报有源IP地址和目标地址
-
每个数据报承载一个传输层报文段
-
每个报文段有一个源端口号和目标端口号
-
-
主机联合使用IP地址和端口号将报文段发送给合适的套接字
无连接的多路解复用
当主机接收到UDP报文时:
-
检查UDP段的目标端口号
-
将UDP报文交送给具备那个端口号的套接字
具备相同目标IP地址和目标端口号,即使是源IP地址且源端口号的IP数据报,将会被传到相同的目标UDP套接字上
面向连接(TCP)的多路复用
TCP套接字:四元组本地标识
解复用:接收主机用这四个值来将数据报定位到合适的套接字
服务器能够在一个TCP端口上同时支持多个TCP套接字
-
每个套接字由其四元组标识
Web服务器对每个连接客户端有不同的套接字
-
非持久对每个请求有不同的套接字
多线程Web Server
-
一个进程下面可能有多个线程,由多个线程分别为客户提供服务
-
在该场景下,还是根据四元组决定将报文段内容发送给同一进程的不同线程
-
解复用到不同线程
无连接传输:UDP
UDP:RFC 768
-
"尽力而为"的服务,报文段可能丢失,可能送到应用程序的报文段乱序
-
无连接:
-
UDP发送端和接收端之间没有握手
-
每个UDP报文都被独立的处理
-
-
UDP被用于
-
流媒体(丢失不敏感,速率敏感,应用可控制传输速率)
-
DNS
-
SNMP
-
-
在UDP上可行可靠传输
-
在应用层增加可靠性
-
应用特定的差错恢复
-
为什么使用UDP
-
不建立连接(会增加延时)
-
简单:在发送端和接收端没有连接状态
-
报文段的头部很小(开销小)
-
无拥塞控制和流量控制:UDP可以尽可能快的发送报文段
UDP校验和
目标
:检测在被传输报文段中的差错
注意:当数字相加时,在最高位的进位要回卷,再加到结果上
可靠数据传输原理
rdt在应用层、传输层和数据链路层都很重要,信道的不可靠性特点决定了可靠数据传输的复杂性
可靠数据传输:问题描述
-
渐增式地开发可靠数据传输协议( rdt )的发送方和接收方
-
只考虑单向数据传输
-
双向数据传输问题实际上时两个单向数据传输问题的综合
-
使用有限状态机(FSM)来描述发送方和接收方
Rdt1.0 :在可靠信道上的可靠数据传输
-
下层的信道时完全可靠的
-
没有比特出错
-
没有分组丢失
-
-
发送方和接收方的FSM
-
发送方将数据发送到下层信道
-
接收方从下层信道接收数据
-
Rdt2.0:具有比特差错的信道
-
下层信道可能会出错:将分组中的比特翻转,用校验和来检测比特差错
-
如何从差错中恢复
-
确认(ACK):接收方显式告诉发送方分组被正确接收
-
否定确认(NAK):接收方显式告诉发送方分组发生了错误
-
发送方接收到NAK会重发分组
-
-
-
rdt2.0中的新机制:采用差错控制编码进行差错检测
-
发送方差错控制编码、缓存
-
接收方使用编码检错
-
接收方的反馈:控制报文(ACK,NAK):接收方->发送方
-
发送方收到反馈相应的动作
-
-
FSM描述
rdt2.1
rdt2.0存在致命缺陷:如果ACK/NAK出错,发送方不知道接收方发生了什么事情,发送方可能会重传(导致重复问题),不重传(导致出错)
需要引入新的机制:序号,用于标识当前需要的分组序号
处理重复:发送方在每个分组中加入序号,如果ACK/NAK出错,发送方重传当前分组,接收方丢弃重复分组,重新发送ACK信号
停等协议:发送方发送一个分组,然后等待接收方应答
FSM描述
-
发送方处理出错的ACK/NAK
-
在分组中加入序列号(0,1,对于每次仅传输一个分组足够了)
-
必须检测ACK/NAK是否出错(需要EDC(error-detection and-correction) )
-
状态数变成了两倍
-
-
接收方处理重复
-
必须检测接收到的分组是否是重复的
-
状态会指示希望接收到的分组序号为0还是1
-
-
rdt2.2 : 无NAK的协议
功能同rdt2.1,但只使用ACK(ack要编号)
接收方对最后正确接收的分组发ACK,以代替NAK
-
接收方必须显示地包含被正确接收分组地序号
当收到重复的ACK(如:再次收到ack0)时,发送方与收到NAK采取相同的动作:重传当前分组、
为后面的一次发送多个数据单位做一个准备
-
一次能够发送多个
-
每一个的应答都有:ACK,NACK;麻烦
-
使用对前一个数据单位的ACK,代替本数据单位的nak
-
确认信息减少一半,协议处理简单
FSM描述
发送方和接收方片段,对比rdt2.1
rdt3.0 : 具有比特差错和分组丢失的信道
引入计时器应对分组丢失
新的假设:下层信道可能会丢失分组(数据或ACK),将会导致死锁问题
方法:发送方等待ACK一段合理的时间(后续会介绍)
-
发送端超时重传:如果到时没有收到ACK->重传
-
问题:如果分组(或ACK )只是被延迟了:
-
重传将会导致数据重复,但利用序列号已经可以处理这个问题
-
接收方必须指明被正确接收的序列号
-
需要一个倒计数定时器
-
FSM描述
rdt3.0的性能
rdt3.0可以工作,但链路容量比较大的情况下,性能很差,链路容量比较大,一次发一个PDU 的不能够充分利用链路的传输能力
流水线:提高链路利用率
流水线
:允许发送在未得到对方确认的情况下一次发送多个分组
-
必须增加序号的范围:用多个bit表示分组的序号
-
在发送方/接收方要有缓冲区
-
发送方缓冲:未得到确认,可能需要重传;
-
接收方缓存:上层用户取用数据的速率≠接收到的数据速率;接收到的数据可
能乱序,排序交付(可靠)
-
两种通用的流水线协议:回退N步(GBN)和选择重传(SR)
通用:滑动窗口(slide window)协议
发送缓冲区
-
发送缓冲区
-
形式:内存中的一个区域,落入缓冲区的分组可以发送
-
功能:用于存放已发送,但是没有得到确认的分组
-
必要性:需要重发时可用
-
-
发送缓冲区的大小:一次最多可以发送多少个未经确认的分组
-
停止等待协议=1
-
流水线协议>1,合理的值,不能很大,链路利用率不能够超100%
-
-
发送缓冲区中的分组
-
未发送的:落入发送缓冲区的分组,可以连续发送出去;
-
已经发送出去的、等待对方确认的分组:发送缓冲区的分组只有得到确认才能删除
-
发送窗口
-
发送窗口:发送缓冲区内容的一个范围(是发送缓冲区的一个子集)
-
那些已经发送但是未被确认分组的序号构成的空间
-
-
发送窗口的最大值 <= 发送缓冲区的值
-
一开始:没有发送任何一个分组
-
后沿=前沿
-
发送窗口的尺寸=0
-
-
发送窗口前沿移动的极限:不能够超过发送缓冲区
-
发送窗口后沿移动
-
条件:收到老分组的确认
-
结果:发送缓冲区罩住新的分组,来了分组可以发送
-
移动的极限:不能够超过前沿
-
接收窗口
-
接收窗口:接收缓冲区
-
接收窗口用于控制哪些分组可以接收;
-
只有收到的分组序号落入接收窗口内才允许接收
-
若序号在接收窗口之外,则丢弃
-
-
接收窗口尺寸Wr=1,则只能顺序接收;
-
接收窗口尺寸Wr>1 ,则可以乱序接收,但提交给上层的分组,要按序
-
-
接收窗口的滑动和发送确认
-
滑动:
-
低序号的分组到来,接收窗口移动;
-
高序号分组乱序到,缓存但不交付(因为要实现rdt,不允许失序),不滑动
-
-
发送确认
-
接收窗口尺寸=1 ; 发送连续收到的最大的分组确认(累计确认)
-
接收窗口尺寸>1 ; 收到分组,发送那个分组的确认(非累计确认)
-
-
发送缓冲区大于1的情况
正常情况下的2个窗口互动
发送窗口
-
有新的分组落入发送缓冲区范围,发送->前沿滑动
-
来了老的低序号分组的确认->后沿向前滑动->新的分组可以落入发送缓冲区的范围
接收窗口
-
收到分组,落入到接收窗口范围内,接收
-
是低序号 ,发送确认给对方
异常情况下GBN的2窗口互动
异常情况下SR的2窗口互动
GBN协议和SR协议的异同
相同之处
-
发送窗口>1,一次能够发送多个未经确认的分组
不同之处
-
GBN:接收窗口尺寸 = 1
-
接收端:只能顺序接收
-
发送端:未得到发送窗口最老分组的确认,后沿不会移动,在得到确认之后会将发送窗口的分组都发出去
-
-
SR: 接收窗口尺寸>1
-
接受端:可以乱序接收
-
乱序:缓存
-
有序:该分组及以前缓存的序号连续的分组交付给上层,然后将窗口移到下一个仍未被接收的分组
-
-
发送端:未得到发送窗口最老分组的确认(后续发送窗口分组已经得到确认),后沿不会移动,但是当收到该分组确认时,只重发该分组
-
流水线协议:总结
Go-back-N:
-
发送端最多在流水线中有N个未确认的分组
-
接收端只是发送累计型确认cumulative ack,接收端如果发现gap(后续分组),不确认新到来的分组
-
发送端拥有对最老的未确认分组的定时器,只需设置一个定时器,当定时器到时时,重传所有未确认分组
Selective Repeat:
-
发送端最多在流水线中有N个未确认的分组
-
接收方对每个到来的分组单独确认individual ack*(非累计确认)
-
发送方为每个未确认的分组保持一个定时器,当超时定时器到时,只是重发到时的未确认分组
GBN | SR | |
---|---|---|
优点 | 简单,所需资源少(接收方一个缓存单元) | 出错时,重传一个代价小 |
缺点 | 一旦出错,回退N步代价大 | 复杂,所需要资源多(接收方多个 |
适用范围 | 出错率低:比较适合GBN,出错非常罕见,没有必要用复杂的SR,为罕见的事件做日常的准备和复杂 | 链路容量大(延迟大、带宽大):比较适合SR而不是GBN,一点出错代价大 |
窗口的最大尺寸
GBN : ; 解释
SR : :解释见下图
由于SR对每个分组都会进行确认,如果超过序号的一半,出现下列情况,接收窗口不知道当前接收的分组是重传的分组还是新分组
面向连接的传输:TCP
TCP:概述
-
点对点:
-
一个发送方,一个接收方
-
-
可靠的、按顺序的字节流
-
没有报文边界
-
-
管道化(流水线)
-
TCP拥塞控制和流量控制窗口大小
-
-
发送和接收缓存
-
全双工数据
-
在同一连接中数据流双向流动
-
MSS
:最大报文段大小
-
-
面向连接
-
在数据交换之前,通过握手(交换控制报文)初始化就发送方,接收方状态变量
-
-
有流量控制
-
发送方不会淹没接收方
-
TCP报文段结构
序号
:报文段首字节在字节流的编号
确认号
: 期望从另一方收到的下一个字节的序号,累积确认
TCP往返延时(RTT)和超时
-
怎样设置TCP超时
-
比RTT要长,但是RTT是变化的
-
太短:太早超时,导致不必要的重传
-
太长:对报文段丢失反应太慢,消极
-
-
怎样估计RTT
-
SampleRTT:测量从报文段发出到收到确认的时间,如果有重传,忽略此次测量
-
SampleRTT会变化,因此估计RTT应该比较平滑,对最近几个测量值求平均,而不是仅用当前的SampleRTT
-
-
-
指数加权移动平均
-
过去样本的影响呈指数衰减
-
推荐值:= 0.125
-
-
设置超时 EstimtedRTT + 安全边界时间
-
EstimtedRTT 变化大 (方差大) 较大的安全边界时间
-
-
SampleRTT 会偏离EstimatedRTT 多远:
-
推荐值:r = 0.25
-
超时时间间隔设置为: =
TCP:可靠数据传输
TCP在IP不可靠服务的基础上建立了rdt
-
管道化的报文段
-
• GBN or SR
-
-
累积确认(像GBN)
-
单个重传定时器(像GBN)
-
是否可以接受乱序的,没有规范
通过以下事件触发重传
-
超时(只重发那个最早的未确认段:SR)
-
重复的确认,3个冗余确认
TCP发送方事件
-
从应用层接收数据
-
用nextseq创建报文段
-
序号nextseq为报文段首字节的字节流编号
-
如果还没有运行,启动定时器
-
定时器与最早未确认的报文段关联
-
过期间隔:TimeOutInterval
-
-
-
超时:
-
重传后沿最老的报文段
-
重新启动定时器
-
-
收到确认
-
如果是对尚未确认的报文段确认
-
更新已被确认的报文序号
-
如果当前还有未被确认的报文段,重新启动定时器
-
TCP:重传
产生TCP ACK的建议
接收方的事件 | TCP接收方动作 |
---|---|
所期望序号的报文段按序到达。所有在期望序号之前的数据都已经被确认 | 延迟的ACK。对另一个按序报文段的到达最多等待500ms。如果下一个报文段在这个时间间隔内没有到达,则发送一个ACK。 |
有期望序号的报文段到达。另一个按序报文段等待发送ACK | 立即发送单个累积ACK,以确认两个按序报文段。 |
比期望序号大的报文段乱序到达。检测出数据流中的间隔 | 立即发送重复的ACK,指明下一个期待字节的序号 |
能部分或完全填充接收数据间隔的报文段到达。 | 若该报文段起始于间隔(gap)的低端,则立即发送ACK |
快速重传
-
超时周期往往太长,在重传丢失报文段之前的延时太长
-
通过重复的ACK来检测报文段丢失
-
发送方通常连续发送大量报文段
-
如果报文段丢失,通常会引起多个重复的ACK
-
-
如果发送方收到同一数据的3个冗余ACK,重传最小序号的段:
-
快速重传
:在定时器过时之前重发报文段,它假设跟在被确认的数据后面的数据丢失了
-
TCP流量控制
接收方在其向发送方的TCP段头部的rwnd字段“通告”其空闲buffer大小
-
RcvBuffer大小通过socket选项设置 (典型默认大小为4096 字节)
-
很多操作系统自动调整RcvBuffer
发送方限制未确认(“in-flight”)字节的个数≤接收方发送过来的 rwnd 值,保证接收方不会被淹没
TCP连接管理
在正式交换数据之前,发送方和接收方握手建立通信关系:
-
同意建立连接(每一方都知道对方愿意建立连接)
-
同意连接参数
同意建立连接
2次握手的失败场景
TCP: 三次握手
3次握手解决:半连接和接收老数据问题
TCP: 关闭连接
客户端,服务器分别关闭它自己这一侧的连接
-
发送FIN bit = 1的TCP段
一旦接收到FIN,用ACK回应
-
接到FIN段,ACK可以和它自己发出的FIN段一起发送
可以处理同时的FIN交换
实际上四次挥手过程存在两军对垒问题,仅供了解
拥塞控制原理
拥塞
:非正式的定义: “太多的数据需要网络传输,超过了网络的处理能力,与流量控制不同
拥塞的表现:
-
分组丢失 (路由器缓冲区溢出)
-
分组经历比较长的延迟(在路由器的队列中排队)
拥塞控制方法
2中常用的拥塞控制方法
-
端到端拥塞控制
-
没有来自网络的显式反馈
-
端系统根据延迟和丢失事件推断是否有拥塞
-
TCP采用的方法
-
-
网络辅助的拥塞控制
-
路由器提供给端系统以反馈信息
-
单个bit置位,显示有拥塞 (SNA, DECbit, TCP/IP ECN, ATM)
-
显式提供发送端可以采用的速率
-
-
ATM ABR拥塞控制
ABR: available bit rate
-
“弹性服务”
-
如果发送端的路径“轻载“
-
发送方使用可用带宽
-
-
如果发送方的路径拥塞了
-
发送方限制其发送的速度到一个最小保障速率上
-
RM(资源管理)信元:
-
由发送端发送,在数据信元中间隔插入
-
RM信元中的比特被交换机设置 (“网络辅助”)
-
NI bit: no increase in rate (轻微拥塞)速率不要增加了
-
CI bit: congestion indication 拥塞指示
-
-
发送端发送的RM 信元被接收端返回, 接收端不做任何改变
在RM信元中的2个字节 ER (explicit rate)字段
-
拥塞的交换机可能会降低信元中ER的值
-
发送端发送速度因此是最低的可支持速率
数据信元中的EFCI bit: 被拥塞的交换机设置成1
-
如果在管理信元RM前面的数据信元EFCI被设置成了1, 接收端在返回的RM信元中设置CI bit
TCP拥塞控制
端到端的拥塞控制机制
-
路由器不向主机提供有关拥塞的反馈信息
-
路由器的负担较轻
-
符合网络核心简单的TCP/IP架构原则
-
-
端系统根据自身得到的信息,判断是否发生拥塞,从而采取动作
拥塞控制的几个问题
-
如何检测拥塞
-
轻微拥塞
-
拥塞
-
-
控制策略
-
在拥塞发送时如何动作,降低速率
-
轻微拥塞,如何降低
-
拥塞时,如何降低
-
-
在拥塞缓解时如何动作,增加速率
-
TCP拥塞控制:拥塞感知
发送端如何探测到拥塞?
-
丢失事件
-
超时时间到,某个段的确认没有来
-
原因1:网络拥塞(某个路由器缓冲区没空间了,被丢弃)概率大
-
原因2:出错被丢弃了(各级错误,没有通过校验,被丢弃)概率小
-
一旦超时,就认为拥塞了,有一定误判,但是总体控制方向是对的
-
-
有关某个段的3次重复ACK:轻微拥塞、
-
网络这时还能够进行一定程度的传输,拥塞但情况要比第一种好
-
如何控制发送端发送的速率
-
维持一个拥塞窗口的值:CongWin
-
发送端限制已发送但是未确认的数据量(的上限),从而粗略地控制发送方的往网络中注入的速率
-
CongWin是动态的,是感知到的网络拥塞程度的函数
-
超时或者3个重复ack,CongWin↓
-
策略:超时时,CongWin降为1MSS,进入SS阶段然后再倍增到CongWin*2(每个RTT),从而进入CA阶段
-
否则(正常收到Ack,没有发送以上情况):CongWin跃跃欲试↑
-
SS阶段:加倍增加(每个RTT)
-
CA阶段:线性增加(每个RTT)
-
-
TCP拥塞控制和流量控制的联合动作
联合控制的方法:发送端控制发送但是未确认的量同时也不能够超过接收窗口,满足流量控制要求
-
SendWin=min{CongWin, RecvWin}
-
同时满足 拥塞控制和流量控制要求
TCP拥塞控制:策略概述
拥塞控制策略:
-
慢启动
-
AIMD:线性增,乘性减少
-
超时事件后的保守策略
TCP慢启动
-
连接刚建立, CongWin = 1 MSS
-
可用带宽可能>> MSS/RTT,应该尽快加速,到达希望的速率
-
当连接开始时,指数性增加发送速率,直到发生丢失的事件
-
启动的初值很低,但是速度很快
-
-
当连接开始时,指数性增加(每个RTT)发送速率直到发生丢失事件
-
每一个RTT, CongWin加倍
-
每收到一个ACK时,CongWin加1
-
慢启动阶段:只要不超时或3个重复ack,一个RTT, CongWin加倍
-
-
总结: 初始速率很慢,但是加速却是指数性的,指数增加,SS时间很短,长期来看可以忽略
TCP拥塞控制:AIMD
乘性减: 丢失事件后将CongWin降为1,将CongWin/2作为阈值,进入慢启动阶段(倍增直到ConWin/2)
加性增:当CongWin>阈值时,一个RTT如没有发生丢失事件 ,将CongWin加1MSS: 探测
当收到3个重复的ACKs:
-
CongWin减半
-
窗口(缓冲区大小)之后线性增长
当超时事件发生时:
-
CongWin被设置成1 MSS,进入SS阶段
-
之后窗口指数增长
-
增长到一个阈值(上次发生拥塞的窗口的一半)时,再线性增加
TCP拥塞控制--总结
-
当CongWin<Threshold, 发送端处于慢启动阶段(slow-start), 窗口指数性增长
-
当CongWin > Threshold, 发送端处于拥塞避免阶段(congestion-avoidance), 窗口线性增长.
-
当收到三个重复的ACKs (triple duplicate ACK),Threshold设置成 CongWin/2,CongWin=Threshold+3
-
当超时事件发生时timeout, Threshold=CongWin/2,CongWin=1 MSS,进入SS阶段
TCP吞吐量
-
TCP的平均吞吐量是多少,使用窗口window尺寸W和RTT来描述?
-
忽略慢启动阶段,假设发送端总有数据传输
-
-
W:发生丢失事件时的窗口尺寸(单位:字节)
-
平均窗口尺寸(#in-flight字节):3/4W
-
平均吞吐量:RTT时间吞吐
-
TCP公平性
TCP是公平的
2个竞争的TCP会话:
-
加性增加,斜率为1, 吞吐量增加
-
乘性减,吞吐量比例减少