目录
3.1 概述和传输层服务
传输服务和协议
- 为运行在不同主机上的应用进程提供逻辑通信(看上去是通过socket api将数据传给另一个进程,实际上报文需要通过层间接口交给传输层,通过两个传输层之间的相互配合交给另一方对等的应用进程)
- 传输协议运行在端系统
- 发送方:将应用层的报文分成报文段,然后传递给网络层
- 接收方:将报文段重组成报文,然后传递给应用层
- 有多个传输层协议可供应用选择
- Internet:TCP和UDP
传输层与网络层
- 网络层服务(IP协议):主机之间的逻辑通信
- 传输层服务:将主机-主机的通信细分为进程间的逻辑通信
- 依赖于网络层的服务(IP协议),依靠传输层无法加强
- 延时(传输、传播、排队等)、带宽(吞吐量,瓶颈链路)
- 并对网络层的服务进行增强(IP向上层提供的服务不可靠,TCP将不可靠变为可靠:RDT。通过SSL将TCP由不安全变为安全)
- 数据丢失、顺序混乱、加密
- 依赖于网络层的服务(IP协议),依靠传输层无法加强
Internet传输层协议
- 可靠的、保序的传输:TCP
- 多路复用、解复用
- 拥塞控制
- 流量控制
- 建立连接
- 不可靠、不保序的传输:UDP
- 多路复用、解复用
- 没有为尽力而为的IP服务添加更多的其它额外服务
- 都不提供的服务(依赖于网络层):
- 延时保证
- 带宽保证
3.2 多路复用与解复用
复用:多个进程应用进程借助一个TCP或UDP实体来发送
在发送方主机多路复用:
从多个套接字接收来自多个进程的报文,根据套接字对应的IP地址和端口号等信息对报文段用头部加以封装(该头部信息用于以后的解复用)
- TCP复用:source port and destination port (TCP header) + message,通过层间接口来到网络层,加上IP头部:IP header(source IP and destination IP) + TCP header + message
- UDP复用:应用进程往下交 1.message 2.socket(source IP and source port) 3.&cad(destination IP and destination port) 给UDP传输层,UDP得到源端口和目标端口并封装信息交给IP网络层,IP知道源IP、目标IP,即可将报文打出
在接收方主机多路解复用:
根据报文段的头部信息中的IP地址和端口号将接收到的报文段发给正确的套接字(和对应的应用进程)
- TCP解复用:收到IP数据报后,拿出IP body部分即TCP段,从TCP头部提取源端口、目标端口,从IP头部提取出源IP、目标IP,从而查询到相应的socket,进而发给相应的进程
- UDP解复用:IP传上来的报文中有源端口和目标端口,通过查询相应的socket发给相应的进程
多路解复用工作原理(UDP和TCP不同)
- 解复用作用:TCP或者UDP实体采用哪些信息,将报文段的数据部分交给正确的socket,从而交给正确的进程
- 主机收到IP数据报
- 每个数据报有源IP地址和目标地址
- 每个数据报承载一个传输层报文段
- 每个报文段有一个源端口号和目标端口号(特定应用有著名的端口号)
- 主机联合使用IP地址和端口号将报文段发送给合适的套接字
面向连接(TCP)的多路复用
- TCP套接字:四元组本地标识:(源IP地址, 源端口号, 目标IP地址, 目标端口号)
- 解复用:接收主机用这四个值来将数据报定位到合适的套接字
- 服务器能够在一个TCP端口上同时支持多个TCP套接字:
- 每个套接字由其四元组标识(有不同的源IP和源PORT)
面向连接的多路复用:多线程Web Server
- 一个进程下面可能有多个线程:由多个线程分别为客户提供服务
- 在这个场景下,还是根据4元组决定将报文段内容同一个进程下的不同线程
- 解复用到不同线程(与解复用到不同进程相似)
3.3 无连接传输:UDP
UDP(User Datagram Protocol [RFC 768]):用户数据报协议
- “尽力而为”的服务,报文段可能丢失也可能送到应用进程的报文段乱序
- 无连接:
- UDP发送端和接收端之间没有握手
- 每个UDP报文段都被独立地处理
- UDP被用于:
- 流媒体(丢失不敏感,速率敏感、应用可控制传输速率)
- DNS
- SNMP(简单网络管理协议)
- 在UDP上可行可靠传输:
- 在应用层增加可靠性
- 应用特定的差错恢复
UDP校验和(校验和:EDC,差错检测码)
- 目标:检测在被传输报文段中的差错(如比特反转),若出错,这个UDP数据报就会被扔掉(表现为丢失)
- 发送方:
- 将报文段的内容视为16比特的整数(每16bit切一段,得到一系列二进制整数)
- 校验和:报文段的加法和(1的补运算)
- 发送方将校验和放在UDP的校验和字段
- 接收方:
- 计算接收到的报文段的校验和
- 检查计算出的校验和与校验和字段的内容是否相等:
- 不相等 --> 检测到差错
- 相等 --> 没有检测到差错,但也许还是有差错
- 残存错误(校验范围 + 校验和 = 1111111111111111,但是两个加数都出错了
3.4 可靠数据传输(rdt)的原理
Rdt1.0:在可靠信道上的可靠数据传输
- 下层的信道是完全可靠的
- 没有比特出错
- 没有分组丢失
- 发送方和接收方的FSM
- 发送方将数据发送到下层信道(只进行接收、封装、打走的动作,不进行其他动作)
- 接收方从下层信道接收数据(解封装、交付)
Rdt2.0:去掉一个假设,变为具有比特差错(如0和1的反转)的信道
- 下层信道可能会出错:将分组中的比特翻转
- 用校验和来检测比特差错
- 问题:怎样从差错中恢复:
- 确认(ACK):接收方显式地告诉发送方分组已被正确接收(send ACK)
- 否定确认(NAK):接收方显式地告诉发送方分组发生了差错(send NAK)
- 发送方收到NAK后,发送方重传分组(之前发送完之后需要保存一个副本)
- rdt2.0中的新机制:采用差错控制编码进行差错检测
- 发送方差错控制编码、缓存
- 接收方使用编码检错
- 接收方的反馈:控制报文(ACK,NAK):接收方->发送方
- 发送方收到反馈相应的动作(发送新的或者重发老的)
Rdt2.0的致命缺陷!-> Rdt2.1
- 如果ACK/NAK出错?
- 发送方不知道接收方发生了什么事情!(既不是ACK也不是NAK)
- 发送方如何做?
- 重传?可能重复
- 不重传?可能死锁(或出错)
- 需要引入新的机制
- 序号
- 处理重复:
- 发送方在每个分组中加入序号
- 如果ACK/NAK出错,发送方重传当前分组
- 接收方丢弃(不发给上层)重复分组
停止等待协议(stop and wait):发送方发送一个分组,然后等待接收方的应答
- 发送方:
- 在分组中加入序列号
- 只需要一位即两个序列号(0,1)就足够了
- 一次只发送一个未经确认的分组(注:若接收方等待的是1号分组,而传来0号未出错的分组,则接收方传回ack,与发送方调成同步)
- 必须检测ACK/NAK是否出错(需要EDC)
- 状态数变成了两倍
- 必须记住当前分组的序列号为0还是1
- 接收方:
- 必须检测接收到的分组是否是重复的
- 状态会指示希望接收到的分组的序号为0还是1
- 注意:接收方并不知道发送方是否正确收到了其最后发送的ACK/NAK
-
发送方不对收到的ack/nak给确认,没有所谓的确认的确认;
-
接收方发送ack,如果后面接收方收到的是:
- 老分组p0?则ack错误
- 下一个分组?P1,ack正确
-
- 必须检测接收到的分组是否是重复的
Rdt2.2:无NAK、只有ACK的协议(NAK free)
- 功能同rdt2.1,但只使用ACK(ack 要编号)
- 接收方对最后正确接收的分组发ACK,以替代NAK(对当前分组的反向确认可由对前一项分组的正向确认代表,如用ack0代表nak1、用ack1代表nak0等等)
- 接收方必须显式地包含被正确接收分组的序号
- 当收到重复的ACK(如:再次收到ack0)时,发送方与收到NAK采取相同的动作:重传当前分组
- 为后面的一次发送多个数据单位做一个准备
- 一次能够发送多个
- 每一个的应答都有:ACK,NACK;麻烦
- 使用对前一个数据单位的ACK,代替本数据单位的nak
- 确认信息减少一半,协议处理简单
Rdt3.0:具有比特差错和分组丢失的信道
- 新的假设:下层信道可能会丢失分组(数据或ACK)
- 会死锁(发送方等待确认,接收方等待分组)
- 机制还不够处理这种状况:
- 检验和
- 序列号
- ACK
- 重传
- 方法:发送方等待ACK一段合理的时间(链路层的timeout时间是确定的,传输层timeout时间是适应式的(需要动态地计算))
- 发送端超时重传:如果到时没有收到ACK->重传
- 问题:如果分组(或ACK)只是被延迟了:
- 重传将会导致数据重复,但利用序列号已经可以处理这个问题
- 接收方必须指明被正确接收的序列号
- 需要一个倒计数定时器
- 过早超时(延迟的ACK)也能够正常工作;但是效率较低,一半的分组和确认是重复的;
- 设置一个合理的超时时间也是比较重要的
Rdt3.0的性能
- rdt3.0停等协议可以工作,但链路容量比较大的情况下(分组全部放完时,分组的第一个比特离接收方还很远),性能很差
- 链路容量比较大,一次发一个PDU的不能够充分利用链路的传输能力(信道明明可容纳很多很多包,每次却只有一个包处于信道中,信道利用率极低)
流水线协议(流水线:允许发送方在未得到对方确认的情况下一次发送多个分组)
- 必须增加序号的范围:用多个bit表示分组的序号(若分组的序号用 N 个比特表示,则整个分组的空间占用是 2N )
- 在发送方/接收方要有缓冲区
- 发送方缓冲:未得到确认,可能需要重传;
- 接收方缓存:上层用户取用数据的速率 ≠ 接收到的数据速率,需要缓冲来对抗数据的不一致性;接收到的数据可能乱序,排序交付(可靠)
- 两种通用的流水线协议:回退N步(GBN) 和 选择重传(SR)
-
发送缓冲区
- 形式:内存中的一个区域,落入缓冲区的分组可以进行检错重发、超时重发
- 功能:用于存放已发送,但是没有得到确认的分组
- 必要性:需要重发时可用
-
发送缓冲区的大小:一次最多可以发送多少个未经确认的分组
- 停止等待协议=1
- 流水线协议>1,合理的值,不能很大,链路利用率不能超100%
-
发送缓冲区中的分组
- 未发送的:落入发送缓冲区的分组,可以连续发送出去;
- 已经发送出去的、等待对方确认的分组:发送缓冲区的分组只有得到确认才能删除
-
发送窗口:发送缓冲区内容的一个范围(发送缓冲区的子集)
- 存放那些已发送但是未经确认分组的序号构成的空间
- 发送窗口的最大值 <= 发送缓冲区的值
- 一开始:没有发送任何一个分组
- 后沿 = 前沿
- 之间为发送窗口的尺寸 = 0
- 发送窗口的移动——前沿移动
- 每发送一个分组,前沿前移一个单位
- 发送窗口前沿移动的极限:(前沿和后沿的距离)不能够超过发送缓冲区
- 发送窗口的移动——后沿移动
- 条件:收到老分组的确认
- 结果:发送缓冲区罩住新的分组,来了分组可以发送
- 移动的极限:不能够超过前沿
- 发送窗口滑动过程——相对表示方法(只是为了方便理解)
- 采用相对移动方式表示,分组不动,窗口向前滑动(实际上真正的滑动过程为窗口不动,分组向前滑动)
- 可缓冲范围移动,代表一段可以发送的权力
接收窗口(receiving window)=接收缓冲区
- 接收窗口用于控制哪些分组可以接收;
- 只有收到的分组序号落入接收窗口内才允许接收
- 若序号在接收窗口之外,则丢弃;
- 接收窗口尺寸Wr=1,则只能顺序接收;
- 接收窗口尺寸Wr>1,则可以乱序接收
- 但提交给上层的分组,要按序
发送窗口-接收窗口的互动
- 正常情况下的2个窗口互动
- 发送窗口
- 有新的分组落入发送缓冲区范围,发送->前沿滑动
- 来了老的低序号分组的确认->后沿向前滑动->新的分组可以落入发送缓冲区的范围
- 接收窗口
- 收到分组,落入到接收窗口范围内,接收
- 是低序号,发送确认给对方
- 发送端上面来了分组->发送窗口滑动->接收窗口滑动->发确认
- 发送窗口
- 异常情况下GBN(wr=1)的2窗口互动
- 发送窗口
- 新分组落入发送缓冲区范围,发送->前沿滑动
- 超时重发机制让发送端将发送窗口中的所有分组发送出去
- 来了老分组的重复确认->后沿不向前滑动->新的分组无法落入发送缓冲区的范围(此时如果发送缓冲区有新的分组可以发送)
- 接收窗口
- 收到乱序分组,没有落入到接收窗口范围内,抛弃
- (重复)发送老分组的确认,累计确认
- 发送窗口
- 异常情况下SR(wr>1)的2窗口互动
- 发送窗口
- 新分组落入发送缓冲区范围,发送->前沿滑动
- 超时重发机制让发送端将超时的分组重新发送出去(不像GBN需要将发送窗口中的所有分组全部重发)
- 来了乱序分组的确认->后沿不向前滑动->新的分组无法落入发送缓冲区的范围(此时如果发送缓冲区有新的分组可以发送)
- 接收窗口
- 收到乱序分组,落入到接收窗口范围内,接收
- 发送该分组的确认,单独确认
- 发送窗口
GBN协议和SR协议的异同
- 相同之处
- 发送窗口>1
- 一次能够可发送多个未经确认的分组
- 不同之处
- GBN:接收窗口尺寸=1
- 接收端:只能顺序接收(对顺序接收的最高序号的分组进行确认-累计确认)
- 对乱序的分组:
- 丢弃(不缓存)
- 在接收方不被缓存!
- 对乱序的分组:
- 发送端:从表现来看,一旦一个分组没有发成功,如:0,1,2,3,4,假如1未成功,234都发送出去了,要返回1再发送;GB1
- 只发送ACK:对顺序接收的最高序号的分组
- 可能会产生重复的ACK
- 只需记住expectedseqnum;接收窗口=1
- 只一个变量就可表示接收窗口
- 只发送ACK:对顺序接收的最高序号的分组
- 接收端:只能顺序接收(对顺序接收的最高序号的分组进行确认-累计确认)
- SR:接收窗口尺寸>1
- 接收端:可以乱序接收
- 发送端:发送0,1,2,3,4,一旦1未成功,2,3,4,已发送,无需重发,选择性发送1
- GBN:接收窗口尺寸=1
3.5 面向连接的传输:TCP
3.5.1 段结构
TCP:
- 向应用进程提供点对点的服务:
- 一个发送方,一个接收方(单点到单点)
- 可靠的、按顺序的字节流:
- 没有报文边界,报文界限靠应用进程自己区分
- 管道化(流水线):
- TCP拥塞控制和流量控制设置窗口大小
- 发送和接收缓存
- 发送缓存区:发完后需要检错重发、超时重传
- 接收缓存区:发送方的发送速率不等于接收方的接收速率,需要接收缓存区匹配速度的不一致性
- 全双工数据:
- 在同一连接中数据流双向流动(同时、双向)
- MSS:最大报文段大小。TCP按照MSS进行报文段的切分,每个MSS报文段前加上TCP头部形成TCP报文段(IP header + TCP header + MSS = MTU(Maixum Transfer Unit, 最大传送单元,表示IP数据报的最大长度(不包括帧头尾),单位为字节))
- 面向连接:
- 在数据交换之前,先建立连接,通过握手(交换控制报文)初始化发送方、接收方的状态变量
- 有流量控制:
- 发送方不会淹没接收方
3.5.2 可靠数据传输
TCP:可靠数据传输
- TCP在IP不可靠服务的基础上建立了rdt
- 管道化的报文段
- GBN or SR
- 累积确认,期望从另一方收到的下一个字节的序号,对顺序到来的最后一个字节给予确认(像GBN)
- 单个重传定时器(像GBN),只和最老的段相关联,一旦超时就将最老的段重发一遍(像SR)
- 是否可以接受乱序的,没有规范
- 管道化的报文段
- 通过以下事件触发重传
- 超时(只重发那个最早的未确认段:SR)
- 重复的确认(又收到3个冗余确认)(又叫快速重传)
- 例子:收到了ACK50,之后又收到3个ACK50
- 首先考虑简化的TCP发送方:
- 忽略重复的确认
- 忽略流量控制和拥塞控制
TCP发送方事件:
- 从应用层接收数据:
- 用nextseq创建报文段
- 序号nextseq为报文段首字节的字节流编号
- 如果还没有运行,启动定时器
- 定时器与最早未确认的报文段关联
- 过期间隔:TimeOutInterval
- 超时:
- 重传 后沿最老的报文段
- 重新启动定时器
- 收到确认:
- 如果是对尚未确认的报文段确认
- 更新已被确认的报文序号
- 如果当前还有未被确认的报文段,重新启动定时器
- 如果是对尚未确认的报文段确认
- 超时周期往往太长:
- 在重传丢失报文段之前的延时太长
- 通过重复的ACK来检测报文段丢失
- 发送方通常连续发送大量报文段
- 如果报文段丢失,通常会引起多个重复的ACK
- 如果发送方收到同一数据的3个冗余ACK,重传最小序号的段;
- 快速重传:在定时器过时之前重发报文段
- 它假设跟在被确认的数据后面的数据丢失了
- 第一个ACK是正常的;
- 收到第二个该段的ACK,表示接收方收到一个该段后的乱序段;
- 收到第3,4个该段的ack,表示接收方收到该段之后的2、3个乱序段,有非常大的可能性为段丢失了
3.5.3 流量控制
目的:接收方控制发送方,不让发送方发送的太多、太快,超过了接收方的处理能力,以至于让接收方的接收缓冲区溢出
TCP流量控制
-
接收方在其向发送方的TCP段头部的rwnd字段“通告”其空闲buffer大小
- RcvBuffer大小通过socket选项设置(典型默认大小为4096字节)
- 很多操作系统自动调整RcvBuffer
-
发送方限制未确认(“in-flight”)字节的个数小于等于接收方发送过来的 rwnd 值
-
保证接收方不会被淹没
-
假设TCP接收方丢弃乱序的报文段,则缓存中的可用的空间: RcvWindow=RcvBuffer−[LastByteRcvd−LastByteRead]
3.5.4 连接管理
连接
- 两个应用进程建立起的TCP连接
- 连接的本质:
- 双方知道要和对方通信
- 为这次通信建立好缓冲区,准备好资源
- 一些控制变量需要做置位,两者需要互相告知自己的初始序号,初始化的RcvBuffer
在正式交换数据之前,发送方和接收方握手建立通信关系:
- 同意建立连接(每一方都知道对方愿意建立连接)
- 同意连接参数
同意建立连接
- Q:在网络中,2次握手建立连接总是可行吗?不行
-
变化的延迟(连接请求的段没有丢,但可能超时)
-
由于丢失造成的重传(e.g. req_conn(x))
-
报文乱序
-
相互看不到对方
-
解决方案:TCP 3次握手(变化的初始序号+双方确认对方的序号)
- 第一次:client-->server:客户端一方的初始序号 x
- 第二次:server-->client:发送确认 ACKnum=x+1 和服务器一方的初始序号 y (捎带)
- 第三次:client-->server:发送确认 ACKnum=y+1 和客户端data(捎带)
CP:关闭连接(连接释放):4次挥手
- 客户端,服务器分别关闭它自己这一侧的连接
- 发送FIN bit = 1的TCP段
- 一旦接收到FIN,用ACK回应
- 接到FIN段,ACK可以和它自己发出的FIN段一起发送
- 可以处理同时的FIN交换
- “对称释放,并不完美”
3.6 拥塞控制原理
拥塞:
- 非正式的定义:“太多的数据需要网络传输,超过了网络的处理能力”
- 与流量控制不同,流量控制是我到你的问题,拥塞控制是网络的问题
- 拥塞的表现:
- 分组丢失(路由器缓冲区溢出)
- 分组经历比较长的延迟(在路由器的队列中排队)
- 网络中前10位的问题!
拥塞的原因/代价:场景1
- 2个发送端,2个接收端
- 1个路由器,具备无限大的缓冲
- 输出链路带宽: R
- 没有重传
- 每个连接的最大吞吐量: R/2 ;当进入的速率 λin 接近链路链路带宽 R 时,延迟增大(此时流量强度趋于1)
场景2:
- 理想化:发送端有完美的信息
- 发送端知道什么时候路由器的缓冲是可用的
- 只在缓冲可用时发送
- 不会丢失:$\lambda_{in}^{'} = \lambda_{in}$
- 理想化:掌握丢失信息
- 分组可以丢失,在路由器由于缓冲器满而被丢弃
- 如果知道分组丢失了,发送方重传分组
- 现实情况:重复
- 分组可能丢失,由于缓冲器满而被丢弃
- 发送端最终超时,发送第2个拷贝,2个分组都被传出
- 此时随着 λin 的增大, λout 也增大,但是由于超时重传的比例越来越大, λout 越来越小于 λin
- 输出比输入少原因:1)重传的丢失分组;2)没有必要重传的重复分组
拥塞的“代价”:
- 延时大
- 为了达到一个有效输出,网络需要做更多的泵入(重传)
- 没有必要的重传,链路中包括了多个分组的拷贝
- 是那些没有丢失,经历的时间比较长(拥塞状态)但是超时的分组,重发没有必要,对本就拥塞的网络雪上加霜(网络加速变坏,非线性)
- 降低了的“goodput”
拥塞的原因/代价:场景3
- 4个发送端
- 多重路径
- 超时/重传
- Q:当 λin′ 、 λin 增加时,会发生什么?
A:当红色的 λin′ 增加时,所有到来的蓝色分组都在最上方的队列中丢弃了,蓝色吞吐->0
2种常用的拥塞控制方法:
- 端到端拥塞控制(自身判断)
- 没有来自网络的显式反馈
- 端系统根据延迟和丢失事件自身推断是否有拥塞
- TCP采用的方法
- 网络辅助的拥塞控制(路由器反馈)
- 路由器提供给端系统以反馈信息
- 单个bit置位,显示有拥塞 (SNA, DECbit, TCP/IP ECN, ATM)
- 显式提供发送端可以采用的速率
- 路由器提供给端系统以反馈信息
3.7 TCP拥塞控制
- TCP拥塞控制采用端到端的拥塞控制机制
- 路由器不向主机有关拥塞的反馈信息
- 路由器的负担较轻
- 符合网络核心简单的TCP/IP架构原则,网络核心提供最小的服务集
- 端系统根据自身得到的信息,判断是否发生拥塞,从而采取动作
- 路由器不向主机有关拥塞的反馈信息
- 拥塞控制的几个问题
- 如何检测拥塞
- 轻微拥塞
- 拥塞
- 控制策略
- 在拥塞发送时如何动作,降低速率
- 轻微拥塞,如何降低
- 拥塞时,如何降低
- 在拥塞缓解时如何动作,尽可能增加速率
- 在拥塞发送时如何动作,降低速率
- 如何检测拥塞
拥塞感知:发送端如何探测到拥塞?
- 某个段超时了(丢失事件):拥塞
- 超时时间到,某个段的确认没有来
- 原因1:网络拥塞(某个路由器缓冲区没空间了,被丢弃) 概率大
- 原因2:出错被丢弃了(各级错误,没有通过校验,被丢弃) 概率小。此时不应该降低发送速率
- 一旦超时,就认为拥塞了,有一定误判(原因2,但概率小),但是总体控制方向是对的
- 有关某个段的3次重复ACK:轻微拥塞
- 段的第1个ack,正常,确认绿段,期待红段
- 段的第2个重复ack,意味着红段的后一段收到了,蓝段乱序到达
- 段的第2、3、4个ack重复,意味着红段的后第2、3、4个段收到了,橙段乱序到达,同时红段丢失的可能性很大(后面3个段都到了,红段都没到)
- 网络这时还能够进行一定程度的传输,拥塞但情况要比第一种好
速率控制方法:如何控制发送端发送的速率
- 维持一个拥塞窗口的值:CongWin(以字节为单位,表示发送方在对方未确认的情况下往网络中注入多少字节)
- 发送端限制已发送但是未确认的数据量(的上限): LastByteSent−LastByteAcked≤CongWin
- 从而粗略地控制发送方的往网络中注入的速率
- CongWin是动态的,是感知到的网络拥塞程度的函数
- 超时或者3个重复ack,CongWin下降
- 超时:CongWin降为1MSS,进入SS阶段然后再倍增到CongWin/2(每个RTT),从而进入CA阶段
- 3个重复ack:CongWin降为CongWin/2, CA阶段
- 否则(正常收到Ack,没有发送以上情况):CongWin跃跃欲试(上升)
- SS阶段(慢启动阶段):每经过一个RTT进行CongWin的加倍
- CA阶段(拥塞避免阶段):每经过一个RTT进行1个MSS的线性增加
- 超时或者3个重复ack,CongWin下降
TCP拥塞控制和流量控制的联合动作
- 联合控制的方法:
- 发送端控制发送但是未确认的量同时也不能够超过接收窗口的空闲尺寸(接收方在返回给发送方的报文中捎带),满足流量控制要求
- SendWin=min(CongWin,RecvWin)
- 同时满足 拥塞控制 和 流量控制 要求
- 发送端控制发送但是未确认的量同时也不能够超过接收窗口的空闲尺寸(接收方在返回给发送方的报文中捎带),满足流量控制要求
TCP 拥塞控制:策略概述
- 慢启动
- 连接刚建立, CongWin=1MSS
- 如: MSS=1460bytes & RTT=200msec
- 则可计算得初始速率为 MSS/RTT=58.4kbps ,这是一个很小的速率,可用带宽可能远远大于它,应当尽快着手增速,到达希望的速率
- 当连接开始时,指数性(后一次速率是前一次的2倍)增加发送速率,直到发生丢失的事件
- 启动初值很低
- 但是速度很快(指数增加,SS时间很短,长期来看可以忽略)
- 当连接开始时,指数性增加(每个RTT)发送速率直到发生丢失事件
- 每一个RTT,CongWin加倍
- 每收到一个ACK时,CongWin加1(等价于每个RTT,CongWin翻倍)
- 慢启动阶段:只要不超时或3个重复ack,一个RTT后CongWin加倍
- 连接刚建立, CongWin=1MSS
- AIMD:线性增、乘性减少
- 乘性减:
- 丢失事件后将CongWin降为1,将CongWin/2作为阈值,进入慢启动阶段(倍增直到CongWin/2)
- 加性增:
- 当CongWin>阈值时,一个RTT如没有发生丢失事件,将CongWin加1MSS:探测
- 当收到3个重复的ACKs:(3个重复的ACK表示网络还有一定的段传输能力(轻微拥塞),超时之前的3个重复的ACK表示“警报”)
- CongWin减半
- 窗口(缓冲区大小)之后线性增长
- 当超时事件发生时:
- CongWin被设置成 1MSS,进入SS阶段
- 之后窗口指数增长
- 增长到一个阈值(上次发生拥塞的窗口的一半)时,再线性增加
- 乘性减:
- 超时事件后的保守策略
- Q:什么时候应该将指数性增长变成线性?
- A:在超时之前,当CongWin变成上次发生超时的窗口的一半
- 实现:
- 变量:Threshold
- 出现丢失,Threshold设置成CongWin的1/2
总结:TCP拥塞控制
- 当CongWin < Threshold,发送端处于慢启动阶段(slow-start),窗口指数性增长。
- 当CongWin > Threshold,发送端处于拥塞避免阶段(congestion-avoidance),窗口线性增长。
- 当收到三个重复的ACKs(triple duplicate ACK),Threshold设置成CongWin/2,CongWin=Threshold+3。
- 当超时事件发生时timeout,Threshold=CongWin/2,CongWin=1MSS,进入SS阶段
TCP 吞吐量
- TCP的平均吞吐量是多少,使用窗口window尺寸W和RTT来描述?
- 忽略慢启动阶段,假设发送端总有数据传输
- 定义W为发生丢失事件时的窗口尺寸(单位:字节),则全过程在W/2和W之间变化
- 平均窗口尺寸(#in-flight字节):3/4W
- 平均吞吐量:RTT时间吞吐3/4W avgTCPthruput=34WRTTbytes/sec
TCP公平性
- 公平性目标:如果 K 个TCP会话分享一个链路带宽为 R 的瓶颈,每一个会话的有效带宽为 R/K
- TCP为什么是公平的?
- 考虑2个竞争的TCP会话:
- 加性增加,斜率为1,吞吐量增加
- 乘性减,吞吐量比例减少
- 考虑2个竞争的TCP会话:
- 公平性和UDP
- 多媒体应用通常不是用TCP
- 应用发送的数据速率希望不受拥塞控制的节制
- 使用UDP:
- 音视频应用泵出数据的速率是恒定的,忽略数据的丢失
- 研究领域:TCP友好性
- 多媒体应用通常不是用TCP
- 公平性和并行TCP连接
- 2个主机间可以打开多个并行的TCP连接
- Web浏览器
- 例如:带宽为R的链路支持了9个连接
- 如果新的应用要求建1个TCP连接,获得带宽R/10
- 如果新的应用要求建11个TCP连接,获得带宽R/2