Transport Layer -- 传输层
传输层服务
传输层协议为运行在不同主机上的应用进程之间提供了逻辑连接
传输层协议运行在端系统上:
- 发送端将应用层报文分解成报文段(segment),传输给网络层
- 接收端将报文段重组为报文段传输给应用层
传输层协议:TCP、UDP
传输层与网络层关系
网络层提供了主机之间的逻辑通信,传输层提供了进程之间的逻辑通信
传输层概述
- UDP--用户数据报协议
提供不可靠、无连接的服务 - TCP--传输控制协议
可靠的、面向连接的服务- 拥塞控制
- 流量控制
- 面向连接
运输层分组被称为数据报
网际协议--IP
英特网网络层协议一个名字叫IP,为主机之间提供了逻辑通信。IP的服务模型为尽力而为交付服务(best-effort delivery service),该模型:
- 不确保报文段的交付
- 不保证报文段按序交付
- 不保证报文段中数据的完整性
因此IP被称为不可靠服务
多路复用与多路分解
作用&原理
在一个主机上运行的多个进程中,每个进程都有着一个或多个套接字,主机需要将到达传输层的报文段定向到合适的套接字,为此,每个报文段中具有几个字段
- 接收端检查这些字段,标识出对应的接收套接字,进而将报文段定向到该套接字,这一过程叫多路分解
- 发送端从不同套接字中收集数据块,并为每个数据块封装上首部信息,从而生成报文段并将其传递到网络层,这一过程为多路复用

实际工作方式
运输层复用的要求
- 套接字有唯一标识符
- 报文段有特殊字段来指示要被交付到的套接字
这些特殊字段是指源端口号字段和目的端口号字段

端口号为以16bits的数,0 ~ 1023为周知端口号,使用受限,专门留给HTTP等周知的应用层协议
无连接的多路复用与多路分解
UDP套接字由一个二元组全面标识,该二元组包含一个目的IP地址和一个目的端口号。两个有不同源IP地址或端口号的UDP报文段,如果有相同的目的IP地址与目的端口号,则它们将通过相同的目的套接字定位到相同进程。
源端口号可被当做“返回地址”的一部分
面向连接的多路复用与多路分解
TCP套接字由一个四元组标识:
- 源IP地址
- 源端口号
- 目的IP地址
- 目的端口号
接收端使用全部的四个值将报文段定向到适当的套接字,与UDP不同,TCP会将不同源IP地址或端口号而具有相同目的IP与端口号的报文段定向到不同的套接字,除非TCP报文段携带了初始创建连接的请求
线程化处理
如今的高性能Web服务器通常只使用一个进程,但会为每个新的用户连接创建一个具有新的连接套接字的线程(可被看作是一个轻量级的子进程)。
UDP(User Datagram Protocol):无连接传输
无连接
基于UDP的应用程序直接与IP“打交道”。UDP从应用程序得到数据,附加上用于多路复用/分解的源和目的端口号字段以及其他两个小字段,将行程的报文段交给网络层,网络层将其封装到一个数据报中后尽力将其交付给接受主机。若报文传到,UDP将数据交付给相应进程。
在这一过程中,发送方与接收方的实体都没有进行握手,因此,UDP被称为是无连接的
UDP应用场景
部分应用更适合用UDP:
- UDP关于发送什么数据以及何时发送数据的应用层上的控制更加精细
- 无需建立连接
- UDP的无连接状态
- UDP分组首部开销更小
UDP报文结构

UDP检验和(checksum)
UDP检验和提供了差错检测的功能,用于确定当UDP报文段从源到达目的地移动时,其中的比特是否发生了改变。
发送方
- 对报文段中所有16bits的字求和
- 求和中若溢出进行回卷
- 求反码
接收方
- 对接收到的段内容进行补码和计算
- 检查计算结果是否与收到的校验和相等
UDP提供差错检验,但对差错恢复没有能力,仅能在差错出现时提供警告
可靠数据传输原理
-
不可靠传输通道的特性将决定可靠传输协议(rdt)的复杂性
-
在应用、传输、链路层都十分重要
-
发送方:
- rdt_send(): 由上层进行调用, (e.g., 应用进程.). 将数据传入发送方并由其传给接收方的上层
- udt_send(): 由rdt调用,将分组通过不可靠的信道传到接收方
-
接收方:
- deliver_data(): 由 rdt调用 将数据递交给上层
- rdt_rcv(): 当数据到达接受方时调用
构造可靠数据传输协议
经完全可靠信道的可靠数据传输--rdt1.0
考虑底层的协议是完全可靠的,即不会有错位与数据丢失
分别为发送方与接收方建立FSM:
- 发送方将数据送入所依赖的信道
- 接收方从所依赖的信道读出数据
FSM:有限状态机--Finite-State Machine

经具有比特差错信道的可靠数据传输--rdt2.0
实际生活的“报文传递”(交谈)中,如果一方听到并理解了对方的“报文”(话),会给与肯定回复,反之会请你重复一遍。这种口述报文传递协议使用了肯定回复与否定回复。
在计算机网络中,这种重传机制的可靠数据传输协议称为自动重传请求协议(ARQ)
ARQ需要另外三种协议功能处理存在比特差错的情况:
- 差错检测
例如UDP的检验和checksum。达到此目的需要额外的比特 - 接收方反馈
- 进行确认 (ACKs): 由接收方法送报文向发送方进行确认
- 发送否认 (NAKs):由接收方法送报文向发送方进行否认,说明分组有错
- 重传
接收方收到有差错的分组,发送方需要重传
rdt2.0的FSM:

rdt2.0发送端有两个状态:
- (图示左边的状态)
发送端协议等待上层传来数据,rdt_send(data)事件出现时,发送方产生一个带有检验和的待发送数据分组(sndpkt),经由udt_send(sndpkt)发送该分组 - (图示右边的状态)
发送方等待来自接收方的ACK或NCK分组- 若收到ACK,说明发送方最*发送的分组已被正确接收,返回左侧状态
- 若收到NCK,重新发送上一个分组并保持该状态等待
- 当发送方处于等待ACK或NCK的状态时,它无法从上层获取更多数据,也不会发送新数据,因此rdt2.0也被称为停等协议。
rdt2.0协议没有考虑ACK或NCK受损的可能性,因此,若一个ACK或NCK分组受损,发送方无法知道接收方是否正确收到
可能的三种解决方案:
- 发送方收到ACK或NCK后再进行一次确认。不实际
- 为ACK与NCK增加足够多的bit。可以直接解决问题
- 当发送方收到含糊不清的ACK或NCK分组分组后重传当前数据分组。会产生冗余分组,导致接收方不知道接收到数据是上次的重传还是新数据
解决ACK或NCK分组可能出现的差错--rdt2.1与rdt2.2
解决冗余分组问题可以通过在数据分组中添加一段新字段:让发送方根据数据的序号对数据进行编号,这样接收方就能通过检验序号来确定发送方是否在重传上一个分组
- 发送方
![rdt2.1Rec]()
- 接收方
![rdt2.1Sen]()
rdt2.2与rdt2.1之间有一处细微的变化,2.2中发送方的sndpkt中必须包含一个ACK报文所确认的分组序号(make_pkt()中加入参数ACK 0或ACK 1,代表最*一次正确接收的数据分组的序号)
- 发送方
![rdt2.2Rec]![]()
- 接收方
![rdt2.2Sen]()
经具有比特差错的丢包信道的可靠数据传输--rdt3.0
底层的信道除了比特差错,还有可能发生丢包的现象。发送方发送一个数据分组,当该分组,或接收方对该分组的ACK发生了丢失,这两种情况下,发送方都不会收到应有的接收方的回应。
要解决这个问题,发送方等待足够长时间来确定分组已经丢失即可。等待的时间至少为一个RRT加上接收方处理一个分组的时间。
如果一个分组经历了非常大的时延但并没有发生丢包,则会产生冗余数据分组,这一问题在rdt2.2中已经得以解决。
为实现基于时间的重传需要一个倒数定时器(countdown timer)。发送方要做到:
- 每发送一个数据分组时,启动一个定时器
- 响应定时器中断
- 终止定时器
- rdt3.0发送方FSM
![rdt3.0]()
rdt3.0的运行情况:
- 无丢包
![noloss]()
- 分组丢失
![pktloss]()
- ACK丢失
![ACKloss]()
- 过早超时
![pretimeout]()
至此,在检验和、序号、定时器、肯定否定分组这些技术共同作用下,至少得到了一个可靠数据传输协议。
流水线可靠数据传输协议
edt3.0协议功能正确,但由于它是一个停等协议,因此存在性能不足的问题
例如:
考虑RTT约为30ms的两个端系统,彼此通过发送速率R=1Gbps的信道相连,分组长L=1000byte;
发送一个分组进入链路的时间为:
\(t_{rans} = \frac{L}{R} = \frac{800bit/pkt}{10^9bit/s} = 8{\mu}s/pkt\)
如果发送方在t=0的时刻开始发送分组,t=8\({\mu}s\)后最后一bit进入发送端信道;
该分组经过15ms到达接收端,其最后一bit在t=15.008ms时到达接收方;
为简化假定接收方接收后立即发送一很小的ACK,则ACK会在t=30.008ms时到达发送方,此后发送方可以发送下一个数据分组;
则发送方的利用率:
\(U_{sender} = \frac{L/R}{RTT+L/T} = \frac{0.008}{30.008} = 0.00027\)
利用率很低。
为解决这个问题,可以允许发送方发送多个分组而无需等待确认,即不以停等的方式运行。这种技术被称为流水线

流水线协议给可靠数据传输协议带来的影响:
- 需要增加序号范围。每个输送中的分组必须有一个唯一的序号,并且此时还可能会有多个传输中的未确认报文
- 协议接收方与发送方都需要缓存多个分组
- 所需序号范围与对缓冲的要求,取决于数据传输协议如何处理丢失、损坏及延时过大的分组。
两种基本解决方法:- 回退N步(Go-Back-N)
- 选择重传(Selective Repeat, SR)
回退N步
回退N步协议(GBN) 允许发送方发送多个分组而不需要等待确认,但流水线中未确认分组最大数不能超过N个
受限原因:TCP的拥塞控制

-
发送方:
![GBDSender]()
GBN的发送方必须响应三种类型事件:
- 上层的调用。 上层调用时首先检查窗口是否已满(有N个已发送未确认分组),未满则将其发送,已满则把数据返回给上层
- 收到一个ACK。 累计确认的方式,表明已经正常收到序号n以及之前的分组
- 超时。 如果出现超时,发送方重新发送所有已发送未确认的分组
-
接收方:
GBN协议中接收方会丢弃所有失序的分组
![GBDRece]()
- 已按顺序收到了n-1个分组,收到第n个分组时接收方为第n个分组发送一个ACK
- 已按顺序收到n个分组,第n个之后若干分组丢失,收到第m个分组,则仍然为第n个分组发送ACK
GBN的运行:

选择重传协议
GBN中一个错误就会就会引起大量分组的重传,随着信道差错率的上升,流水线可能被不必要的重传分组充斥。
选择重传协议(SR)通过让发送方重传那些它怀疑接收方未正常收到的分组,从而避免了不必要的重传。

发送方
- 从上层收到数据
收到数据后,发送方检查可分配给该该分组的序号- 序号在窗口内,则打包发送
- 在窗口范围之外,则将其缓存或返回给上层
- 超时
每个分组拥有自己的定时器,超时后只重发一个分组 - 收到ACK
- 收到ACK的序号等于send_base指针,则先把其标为已接收,然后将send_base移到后面最*的一个已发送未接收的分组
- 若ACK的序号在窗口内,直接将其标为已接收
接收方
- 收到的分组序号在[rcv_base, rcv_base+N-1]内,返回一个ACK,若是第一次收到,则缓存该分组。如果序号等于rcv_base,把自rcv_base及往后的连续的已缓存分组传给上层
- 序号在[rcv_base_N, rcv_base-1]内,返回一个ACK(因此编码范围需要至少等于2N)
- 其他情况忽略该分组

面向连接的协议--TCP
TCP连接
TCP是面向连接的:在一个应用进程可以开始向另一个应用进程发送数据前要先相互“握手”,即相互发送某些预备报文段,以确保数据传输的参数。
与电路交换网络中的一些端到端电路不通,TCP是一种“逻辑”连接,其共同状态只保留在两个通讯端系统的TCP程序中,其中间的网络元素(如路由器)并不会保持其连接状态。
TCP提供的是全双工服务:
- 进程A、B间存在一条TCP,应用层数据可以在从B到A的同时,也从A流向B。
TCP连接也总是点对点的,即连接存在于单个的发送方与接收方之间。
建立连接
三次握手。前两次不包括应用层数据,第三次可以包括。
发送数据
- TCP将数据引导到发送缓存中,这是发起三次握手期间设置的缓存之一
- TCP适时地取出一块数据,并将其传递到网络层。数据的数量受限于最大报文段长度MSS,而MSS又由MTU,本地发送方发送数据的最大传输单元,所决定。
例如因特网和PPP链路层都有1500Byte的MTU,而TCP/IP首部长度为40Byte,则MSS一般设置为1460Byte
- TCP为每块客户数据加上一个TCP首部,从而形成TCP报文段,下传给网络层后网络层将其分别封装在网络层IP数据报中传输给接收方
- TCP在接收端收到报文段后将数据放入接收缓存区,等待应用程序读取
TCP报文段结构

TCP报文段首部
- 源端口号和目的端口号用于对上层数据的多路复用/分解
- 检验和字段
- 序号字段和确认号字段用于实现可靠数据传输
- 接收窗口字段用于流量控制
- 首部长度字段指示了32bit为单位的TCP首部的长度
- 选项字段用于发送方接收方协商MSS,或在高速网络环境下作为窗口调节因子使用
- 标志字段,ACK、RST、SYN、FIN、PSH、URG
序号与确认号
TCP把数据看成一个无结构、有序的字节流,序号是建立在传送的字节流之上:一个报文段的序号是该报文段首字节的字节流编号。
确认号:接收方期待从发送方主机收到的下一字节的序号

telnet示例:

往返时间估计与超时
超时时间应该设置的比RTT略长:
- 过短:出现不必要的重传
- 过长:降低效率,减缓了对丢包的反应
估计往返时间
报文段的样本RTT--SampleRTT从某报文段被发出到该报文段被确认收到的时间。
大部分TCP在任一段给定时刻内,仅会为单个已发送但还未被确认的分组计算SampleRTT,此外,它绝不会为已被重传的报文段计算SampleRTT。
由于路由器的拥塞和端系统负载的变化,这些报文段的SampleRTT也会波动,为估计一个典型的RTT,TCP会维持一个SampleRTT的均值,每次获得一个新的SampleRTT,就会对EstimatedRTT更新:
\(EstimatedRTT = (1 - \alpha)*EstimatedRTT + \alpha*SampleRTT\)
[RFC 6298]中推荐的\(\alpha\)值为0.125
在统计学意义上,这种*均被称为指数加权移动*均。
RTT样本与RTT估计

测量RTT的变化也是有意义的。[RFC 6298]定义了RTT的偏差DevRTT,用于估算SampleRTT偏离EstimatedRTT的程度:
\(DevRTT = (1-\beta)*DevRTT + \beta*|SampleRTT - EstimatedRTT|\)
\(\beta\)推荐值为0.25
设置和管理重传超时间隔
\(TimeoutInterval = EstimatedRTT + 4*DevRTT\)
- 初始的TimeoutInterval值为1秒
- 出现超时后TimeoutInterval值将翻倍,避免后续报文段过早超时
- 重新收到ACK并更新EstimatedRTT后就会重新计算TimeoutInterval
可靠数据传输
TCP在IP不可靠的尽力而为服务上创建了一种可靠数据传输服务,确保一个进程从其接收缓存中读出的数据流是无损坏、无间隙、非冗余与按序的数据流。
- 累计ACK
- 单一重传计时器
简化的TCP发送方(伪代码):
/**假设:
**发送方不受TCP流量和拥塞限制的控制
**来自上层的数据小于MSS
**数据的传输只在一个方向进行
**/
NextSeqNum = InitialSeqNumber;
SendBase = InitalSeqNumber;
while(1){
switch(事件)
case: 从上层应用程序接收到数据e
生成具有序号NextSeqNumber的TCP报文段;
if(定时器当前没有运行)
启动定时器;
向IP传递报文段;
NextSepNumber += length(data);
break;
case: 定时器超时
重传仍未应答报文段中序号最小的一个;
启动定时器;
break;
case: 收到ACK,具有ACK字段值y
if(y > SendBase){
SendBase = y;
if(目前还存在未应答的报文段){
启动定时器;
}
}
break;
}
三个重传情景
- 由于ACK丢失而重传
![]()
- 过早超时,累计确认,避免Seq100重传
![TCp2]()
- 累积确认,避免第一个报文段的重传
![TCP3]()
超时后间隔加倍
与上节所描述的不同,大多数TCP的实现中,TCP每次重传时都会把下一次的超时间隔置为先前值的二倍,而不是用从EstimatedRTT和DevRTT推算出的值。
快速重传
超时触发重传问题之一是超时周期可能相对较长。当发送方一个报文段丢失时,长超时周期迫使发送方延迟重传已发送分组。
但是,发送方通常可以在超时事件前通过注意冗余ACK来检测丢包状况。
冗余ACK:发送方收到对某段报文段的确认后再次收到对该报文段的ACK
TCP ACK生成策略:

TCP快速重传:如果发送方收到同一报文段的3个ACK,说明在这个被确认过3次的报文段之后的报文段已经丢失
可用以下伪代码片段替代上段switch内的case: 收到ACK,具有ACK字段值y
case: 收到ACK,具有ACK字段值y
if(y > SendBase){
SendBase = y;
if(目前还存在未应答的报文段){
启动定时器;
}
}else{
y收到的冗余ACK数加一;
if(y收到的冗余ACK数 == 3){
/* TCP快速重传 */
重发具有序号y的报文段;
}
}
break;
流量控制
TCP连接每一侧的主机都为连接设置了接收缓存,当该TCP连接收到正确、按序的字节之后就将其数据放入接收缓存。由于缓存区大小与上层应用程序的读取速度都是有限的,如果发送方发送得太多、太快,接收方的缓存很容易发生溢出。
TCP为它的应用程序提供了流量控制服务来防止接收方缓存发生溢出。因此,流量控制是一个速度匹配服务,及发送方的发送速率与接收方应用程序的读取速率匹配。
TCP通过让发送方维护一个称为接收窗口的变量来提供流量控制,用于给发送方指示该接收方还有多少可用缓存空间
定义:
- LastByteRead: 接收方主机的应用程序从缓存读出的最后一个字节的编号
- LastByteRecd: 从网络中到达并已放入主机B接收区缓存的最后一个字节的编号
则必须有:
\(LastByteRcvd - LastByteRead \leq RcvBuffer\)
接收窗口rwnd根据缓存可用空间的数量设置:
\(rwnd = RecvBuffer - [LastByteRcvd - LastByteRead]\)
- RcvBuffer 大小可通过socket选项来设定(缺省为4096字节)
- 许多操作系统可自动调整RcvBuffer大小

该方案存在的问题:由于TCP连接的接收方只会在确认已收到数据时向发送方发送字节,因此,当接收方缓存满了之后向发送方发送一个rwnd=0的ACK,这时发送方停止发送数据,而在接收方应用程序读取了数据,缓存区有了新的空间后发送方无从得到这一信息,就无法再次开始发送数据。
因此,TCP要求在接收方的接收窗口为0时,发送方要持续发送只有一个字节大小的报文段,接收方有了缓存空间之后向发送方ACK。
TCP连接管理
建立连接
客户中的TCP会通过如下方式与服务器中的TCP建立一条TCP连接:
- 客户端TCP首先向服务器TCP发送一个特殊报文段,其中不会包括应用层数据,但报文段首部的SYN标志位被置为1,因此该报文段也被称为SYN报文段。另外客户会随机地选择初始序号(cilent_isn),并将其置于报文段的序号字段中。
- 服务器主机收到SYN报文段后为该TCP连接分配缓存和变量,并向客户端TCP发送允许连接的报文段。报文段首部中,SYN被置为1,ACK确认号字段被置为cilent_isn+1,服务器选择自己的初始序号(server_isn)并将其放到序号字段中。该报文段被称为SYNACK报文段。
- 收到SYNACK后,客户端给连接分配缓存和变量,并通过一个报文段进行确认。此时连接已经建立,这个阶段的报文段可以携带需要发送的数据。
这种创建连接的过程也叫三次握手

三次握手的FSM:

关闭连接
参与TCP连接的每一方都可以关闭该链接。
关闭过程:
- 客户端关闭插口: clientSocket.close();
- Step 1: 客户端 end system 发送 TCP FIN 控制段给服务器
- Step 2: 服务器 收到 FIN, 用 ACK应答. 关闭连接, 发送 FIN.
- Step 3: 客户端 收到 FIN, 用 ACK进行应答. 随着对接收到的FIN发送ACK-同时进入 “timed wait(计时等待)”
- Step 4: 服务器, 接收 ACK. 连接关闭.

客户端与服务器端经历的典型的TCP状态序列:


拥塞控制原理
拥塞:
- 非正式的说法: “过多信源以过快的速率发送了过多的数据、导致网络穷于应付”
- 后果:
- 丢失数据分组 (路由器缓存溢出)
- 长时间的延迟 (在路由器的缓存中排队)
拥塞原理与代价
情景1:两个发送方和一台具有无穷大缓存的路由器
- 两个发送端, 两个接收端
- 一个路由器, 无限缓存
- 输出链路带宽 R 共享式输出
- 无重传机制

情况2:两个发送方和一台具有有限缓存的路由器

- 一个路由器, 有限缓存
- 发送端重传丢失的分组
- \(\lambda_{in}\): 应用程序将数据发送到套接字的速率
- \(\lambda^{'}_{in}\): 供给负荷,运输层向网络层发送的速率。
-
考虑一种理想状态,发送方可以得知路由器缓存是否已满,并仅在路由器还有空闲缓存时发送数据。这种情况下不会发生丢包,\(\lambda_{in}=\lambda^{'}_{in}\)
![]()
-
考虑一种更真实的情况,发送方确认仅在一个分组丢失后重传。这种情况下可见一种网络拥塞的代价:发送方必须执行重传已补偿因为缓存溢出而丢包的分组。
![]()
-
发送方发送的未丢失的分组会在排队时提前超时,导致该分组重发。这种情况下,路由器转发重发的那个分组是无用的。可见网络拥塞的另一个代价:发送方在遇到大时延时进行的不必要的重传会导致路由器使用其链路发送不必要数据。
![]()
情景3:4个发送方和具有有限缓存的多台路由器及多条路径

A --> C : R1, R2
B --> D : R2, R3
相比主机A,主机B离R2更*,在与主机A的竞争中会逐渐处于优势,导致A的传输效率降低。当B的\(\lambda_{in}\)不断升高,A的分组会被丢弃,直到变成0.
代价3:当分组被丢弃时, 所有“上游”信道为该分组所作的工作统统被浪费了
拥塞控制的方法
可以根据网络层是否为运输层拥塞控制提供了显示帮助来区分拥塞控制方法:
- 端到端拥塞控制(未提供显示帮助): 网络层若存在拥塞,端系统必须通过对网络行为的观察推断。如通过TCP报文段的丢失缩短窗口长度
- 网络辅助的拥塞控制: 路由器向发送方提供关于网络中拥塞状态的显示反馈信息。例如ATM可用比特率拥塞控制中,路由器显示地通知发送方自己能在输出链路支持的最大主机发送速率。
TCP拥塞控制
TCP所采取的方法:让发送方根据所感知到的拥塞程度控制发送流量的速率。
- 发送方如何限制其发送速率?
增加一个变量拥塞窗口cwnd,规定发送方未确认的分组数不得超过cwnd与rwnd的最小值;在忽略接收窗口的情况下,发送方缓存中未发送数将受cwnd约束,它也会间接约束发送速率。 - 发送方如何感知链路上存在拥塞?
定义接收方的“丢包事件”为:要么出现超时,要么接收到三个冗余ACK。出现过度拥塞时,路由器缓存溢出引起包含着TCP报文段的数据报丢失,丢失的数据报接着会引起发送方的丢包事件,发送方就感知到了拥塞。 - 发送发感知到拥塞后采取什么策略控制速率?
带宽检测: ACK到来指示无拥塞,丢包事件指示出现拥塞。TCP的策略是在收到ACK时不断增加发送速率,直到出现丢包事件,一定程度降低速率后重复该过程
TCP拥塞控制算法
包括三部分:慢启动、拥塞避免与快速恢复。慢启动和拥塞避免为TCP强制部分,快速恢复为推荐部分。
FSM

慢启动
在慢启动状态,cwnd以1个MSS开始,而且每当一个非重传的报文段被确认cwnd翻倍。
如果存在一个由超时指示的丢包事件:将cwnd置为1。
初始速率满,指数增长快。

拥塞避免
- 慢启动阈值:ssthresh
- 在cwnd达到ssthresh前指数增长,达到后慢启动变为线性增长
- 慢启动发生拥塞(timeout或冗余ACK),在将cwnd置为1的同时把ssthresh置为cwnd/2,然后开始新的慢启动过程
收到冗余ACK并快重传时,进行快恢复。
快速恢复
由于收到冗余ACK而触发丢包事件,将cwnd降为一半,而不是降为1。

对TCP吞吐量的宏观描述
TCP的控制策略:每个RTT内线性增加一个MSS,出现冗余ACK后减半。因此其策略常被成为AIMD(线性增加,减少减半)的控制策略。
忽略慢启动的阶段,对TCP的稳态行为建立一个高度简化的宏观模型:

所以,对一条链路而言:
公*性
公*性:对K条具有不同端到端路径,但都经过一条R bps的瓶颈链路,如果每条连接的*均传输速率都接*R/K,则说明其拥塞控制机制是公*的。
考虑两段TCP连接,给定时刻二者吞吐量之和小于R,对应图中起始点,然后二者吞吐量同速率增加(斜率为45°),当其吞吐量和大于R后,二者吞吐量介减半,然后继续同速率增加。这一过程逐渐趋*于*等宽带共享的直线。因此TCP具有公*性。

公*性与UDP
TCP是通过拥塞窗口进行拥塞控制,但这并不会作用于UDP。当TCP在面对拥塞降低传输速率时,UDP并不会这样做,因此TCP流量可能被UDP压制。
公*性与并行TCP连接
主机间应用存在多个并行的连接,如浏览器:
- 9个连接在R的链路上:增加1个TCP,可获得R/10;
- 如果增加11个,可获得R/2

















posted on
浙公网安备 33010602011771号