计网学习笔记十二.传输层(下)

目录

 

TCP概述

段结构

序列号和ACK、累计应答

TCP可靠数据传输

如何设置定时器的超时时间?

TCP发送方细讲

TCP重传示例

TCP接收方细讲

快速重传

TCP可靠性遗留问题

TCP流量控制

TCP连接管理(三次握手,四次挥手)

三次握手

为什么要三次握手?

序号问题。

连接建立

四次挥手(连接关闭)

正常情况

异常情况,为什么要四次挥手?

状态时序图

TCP状态机

拥塞控制原理

拥塞的成因和代价

场景1:导致分组延迟 太大

场景2:降低吞吐量

场景三:多跳网络,吞吐量更低

拥塞控制的方法


TCP概述

段结构

segment-翻译为段,报文段。

有些字段没用,所以当时设计现在没用,还有改进空间

序列号和ACK、累计应答

  • 序列号是段中的第一个字节大小,不是第几个段。(序号的具体细节在连接管理中介绍,三次握手四次挥手)
  • 建立tcp,双方各有一个序号,在三次握手时会细讲
  • ACK n+1,代表n之前的包(包括n)都收到了,希望收到的下一个包序号为n+1。
  • 乱序到达的包,接受放怎么处理,由实现者决定。

TCP可靠数据传输

这些特点是GBN和SR中和的,每个特点下面会降到。包括两种触发重传的情况

如何设置定时器的超时时间?

补充:

估计往返时间,需要 TCP 通过采样 RTT 的时间,然后进行加权平均,算出一个值,而且这个值还是要不断变化的,因为网络状况不断地变化。除了采样 RTT,还要采样 RTT 的波动范围,计算出一个估计的超时时间。由于重传时间是不断变化的,我们称为自适应重传算法(Adaptive Retransmission Algorithm)。如果过一段时间,5、6、7 都超时了,就会重新发送。接收方发现 5 原来接收过,于是丢弃 5;6 收到了,发送 ACK,要求下一个是 7,7 不幸又丢了。当 7 再次超时的时候,有需要重传的时候,TCP 的策略是超时间隔加倍。每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送。

TCP发送方细讲

  • 从应用层收到数据就这几个操作。
  • 超时后,重发引起超时的段,注意是引起超时的段,不是所有,假设发送了1-10,1-5收到了ACK,6超时还没收到,只重传6,每个段的超时时间可能不一样。
  • 重发后,应该重启定时器,重新计时
  • 收到ACK n,如果之前没确认过的分组,则更新sendbase=n。 如果窗口还有没确认的分组,重启计时器?这个不明白,收到1组,为什么要重启2组的计时器?

三种协议的超时区别:

  • GBN:首先明白,三种都是流水线协议,即可以同时发送多个分组。比如一次发了10个,GBN这十个是同一个计时器,如果超时,则重发10个分组
  • SR:同时发送10个分组,但每个分组设置一个定时器,谁超时了重发谁,互不影响
  • TCP:课上没有明确讲,结合后面的内容,下面程序似乎是多个组共用一个计时器,但百度百科上说每个报文都有一个计时器!有四种计时器,这块待定

三种协议的ACK:

  • GBN:接收方发ACK n,代表n之前都正确接受。如果乱序到达,接收方直接丢弃
  • SR:ACK n,只代表第n组正确接受。如果乱序到达,会缓存乱序的分组
  • TCP:ACK n,代表n-1及其之前都正确接受,期待下一组序号是n。乱序到达,没规定怎么处理,由实现者决定。

发送端程序

  • 初始化SendBase,和NextSeqNum
  • 从上层接收到数据,创建段,使用初始的NextSeqNum做序号,开启计时器,发送数据到IP层,下一个发送的段序号为:NextSeqNum+数据字节数
  • 超时,重发没有收到ACK的最小序号的段
  • ACK收到,如果对应的段序号y>sendbase,则意味着y以前的包都正确接受,将sendbase更新=y。如果窗口仍然有未收到ACK的段,则重启计时器!不明白,难道窗口中共用一个计时器?

TCP重传示例

ACK丢失,100=92+8,代表接收方期望下个段序号是100.超时后,发送方重新发送。

  • 纵坐标写的是序号92的超时时间,没说是100的超时,即发送了两个段,虽然接收方ACK了两个,但发送方认为92超时,重发92。
  • 重发后收到了两个ACK,就分别更新sendbase=100,再次更新120,表示两个段已正确发送,更新窗口大小。
  • 接收方一直期望下个段是120,但却收到重发的100,于是丢弃100段,再次ACK120,标明接收方需要120

  • 发送了两个段92和100,但第一个ACK100丢失了
  • 第二个ACK120正确给了发送方,因为还没到92组的超时时间就收到了ACK120,所以发送方认为120以前的分组全部正确发送,更新窗口大小到120.

TCP接收方细讲

  1. 到达了一个按序的段,在此段之前,所有段都已经ACK了,对应操作:延迟发此段的AK,等到500ms,如果没有下个段来,就发ACK
  2. 如果达到一个按序段,在此之前,有一个段还没有发送ACK,对应操作:立刻发送这两个段的累计应答ACK,这样只发一个ACK就可以确认两个段。
  3. 如果乱序段到达,对应操作:立刻发送"重复ACK",标明接收方需要的段是哪个,并非当前的乱序段。

快速重传

  • 如果发送超时,重发段后,新设置的超时时间会加倍!
  • 接收方收到乱序到达段,会发送ACK n,标明需要的是段n
  • 如果发送方收到三次ACK n,发送方就认为 段n丢失了,不会等到n 的计时器超时,就可以重传 段n

TCP可靠性遗留问题

四种计时器?重发计时器,可能是每个报文一个计时器,不是共用一个,课上对计时器说的太模糊.

网上补充:

TCP中的四个计时器包括重传计时器、坚持计时器、保活计时器、时间等待计时器

重传计时器(Retransmission Timer):
目的:为了控制丢失的报文段或者丢弃的报文段。这段时间为对报文段的等待确认时间。
创建时间:在TCP发送报文段时,会创建对次特定报文段的重传计时器。
可能发生的两种情况:在截止时间(通常为60秒)到之前,已经收到了对此特定报文段的确认,则撤销计时器;在截止时间到了,但为收到对此特定报文段的确认,则重传报文段,并且将计时器复位。
重传时间:2*RTT(Round Trip Time,为往返时间)


坚持计时器(Persistent Timer):
目的:主要解决零窗口大小通知可能导致的死锁问题
死锁问题的产生:当接收端的窗口大小为0时,接收端向发送端发送一个零窗口报文段,发送端即停止向对端发送数据。此后,如果接收端缓存区有空间则会重新给发送端发送一个窗口大小,即窗口更新。但接收端发送的这个确认报文段有可能会丢失,而此时接收端不知道已经丢失并认为自己已经发送成功,则一直处于等待数据的状态;而发送端由于没有收到该确认报文段,就会一直等待对方发来新的窗口大小,这样一来,双方都处在等待对方的状态,这样就形成了一种死锁问题。如果没有应对措施,这种局面是不会被打破的。为了解决这种问题,TCP为每一个连接设置了坚持计时器。
工作原理:当发送端TCP收到接收端发来的零窗口通知时,就会启动坚持计时器。当计时器的期限到达时,发送端就会主动发送一个特殊的报文段告诉对方确认已经丢失,必须重新发送。【这个特殊的报文段就称为探测报文段,探测报文段只有1个字节的大小,里边只有一个序号,该序号不需要被确认,甚至在计算其他部分数据的确认时该序号会被忽略。】
截止期的设置:设置为重传时间的值。但如果没有收到接收端的响应,则会发送另一个探测报文段,并将计时器的值加倍并复位,直到大于门限值(一般为60秒)。在此之后,发送端会每隔60秒发送一个探测报文段,直到窗口重新打开。


保活计时器(Keeplive Timer):
目的:主要是为了防止两个TCP连接出现长时间的空闲。当客户端与服务器端建立TCP连接后,很长时间内客户端都没有向服务器端发送数据,此时很有可能是客户端出现故障,而服务器端会一直处于等待状态。保活计时器就是解决这种问题而生的。
工作原理:每当服务器端收到客户端的数据时,都将保活计时器重新设置(通常设置为2小时)。过了2小时后,服务器端如果没有收到客户端的数据,会发送探测报文段给客户端,并且每隔75秒发送一个,当连续发送10次以后,仍没有收到对端的来信,则服务器端认为客户端出现故障,并会终止连接。


时间等待计时器(Time_Wait Timer):
时间等待计时器是在连接终止期间使用的。
当TCP关闭连接时并不是立即关闭的,在等待期间,连接还处于过渡状态。这样就可以使重复的FIN报文段在到达终点之后被丢弃。
时间设置:一般为报文段寿命期望值的2倍。

TCP流量控制

  • Buffer是缓冲,RevBuffer是总共能缓冲的数据大小,数据从IP传来,RevWindow是能够接收的窗口大小,spareroom剩余空间可缓存数据的,然后application process从缓冲中拿数据。
  • 如果发送方发送过快,buffer占满,则接收方会把溢出的数据丢失。

  • buffer剩余空间=总大小-(LastByteRcvd - LastByteRead) ,上次接收到-上次读取的(读取的就是应用层拿的,应用层读取一个字节,则这个字节就可以删除不占用空间了,所有上次接受的-上次读取的就是应用层读取后还占据的空间)
  • 接收方会把剩余buffwe,即RevWindow接受窗口大小放在头部字段告诉发送方
  • 发送方就可以限制自己发送的数据量,防止buffer溢出
  • RecWindow=0? 如果发送方完全不发消息,即使接收方RevWindow有值了,发送方也不知道,会变为死锁。所以即使等于0,发送方依然可以发送一个很小的段(窗口探测数据包),以便接收方回复信息,会告诉新的RevWindow,防止死锁
  • 当接收方比较慢的时候,要防止低能窗口综合征,别空出一个字节来就赶快告诉发送方,然后马上又填满了,可以当窗口太小的时候,不更新窗口,直到达到一定大小,或者缓冲区一半为空,才更新窗口。

TCP连接管理(三次握手,四次挥手)

这里解释清双方 都有序号的问题,双方序号互不干涉

  • 建立连接,要初始化变量,有段序号、buffer
  • client是连接发起者,server是等待client建立连接请求

三次握手

  1. 握手1:客户端主机发送TCP SYN段到server,在前面的段结构中讲过几个标志位,S代表SYN,发送方的第一次握手中段会将SYN置为1,设置一个初始序号(),并且段不携带任何数据。 
  2. 握手2:服务端收到SYN报文段,回复一个SYNACK报文段,服务端就会分配初始资源buffer,确定一个server端的初始序号,并且把序号告诉client端。
  3. 握手3:客户端收到了SYNACK报文段,回复一个ACK报文段,这个段里,SYN标志位不是1,ACK应该是1,并且这个报文段就可以携带数据了。

为什么要三次握手?

为什么不是两次?确保client 和server端发出的报文段都能收到ACK,如果只有两次握手,那server发出的报文(第二次握手)就没有收到ACK。保证双方的消息都是有去有回

为什么不是四次,十次?完全可以给client的ACK再回复一个ACK,这样就无线套娃了,只要保证消息有去有回就可以。

而且大部分情况A 和 B 建立了连接之后,A 会马上发送数据的,一旦 A 发送数据,则很多问题都得到了解决。例如 A 发给 B 的应答丢了,当 A 后续发送的数据到达的时候,B 可以认为这个连接已经建立,或者 B 压根就挂了,A 发送的数据,会报错,说 B 不可达,A 就知道 B 出事情了。

当然你可以说 A 比较坏,就是不发数据,建立连接后空着。我们在程序设计的时候,可以要求开启 keepalive 机制,即使没有真实的数据包,也有探活包。

序号问题。

前面课程说是包中第一个字节数,下个段序号是初始序号+第一个段的字节大小,但这节课又说client发起连接的初始序号是随机很复杂,无语了前后不一。根据极客时间的课程,建立连接的初始序号跟时间有关,很复杂。以下是极客时间资料:

连接建立

  1. client发送报文段,SYN=1,client设置一个seq序号为client_isn
  2. server回复client报文段,SYN=1,server设置一个seq序号server_isn,ack序号为client_isn+1(表示期望收到下一个client报文段序号是client_isn+1)
  3. cient收到ACK,发送报文段SYN=0,seq=client_isn+1,ack是server_isn+1(表示期望收到的下一个server报文段序号是server_isn+1)
  4. 前面看到,在三次握手,第二次握手后,服务器会分配一些初始资源,如果第三次握手迟迟失败(客户端没有发送ACK),就会把这些资源释放掉。如果同一时刻,大量客户端建立连接,却不发送ACK确认真正建立连接,这样服务器会浪费很多资源,这就是一种网络攻击手段。

四次挥手(连接关闭)

正常情况

A:B 啊,我不想玩了。

B:哦,你不想玩了啊,我知道了。

B:A 啊,好吧,我也不玩了,拜拜。

A:好的,拜拜。

异常情况,为什么要四次挥手?

尽量保证client和server都能关闭资源!保证双方的消息都有回复。

  • client第一次FIN后,client立刻关闭,万一FIN没发送到sever,server就关不了
  • server发送了ACK,立刻关,client也不知道server已经关了,而且server还有未处理完的数据需要继续发送
  • server发送了FIN ACK,立刻关,万一FIN ACK丢失,client就不知道server关了
  • 最后client发送ACK,等待很长的时间,确保Server收到最后的ACK,如果server没收到ACK,会重发FIN ACK,client就知道server没收到最后的ACK,client会重发ACK。但client不能无限等下去,重发后还不行,会发送RST,就立刻关闭。

A 开始说“不玩了”,B 说“知道了”,这个回合,是没什么问题的,因为在此之前,双方还处于合作的状态,如果 A 说“不玩了”,没有收到回复,则 A 会重新发送“不玩了”。但是这个回合结束之后,就有可能出现异常情况了,因为已经有一方率先撕破脸。一种情况是,A 说完“不玩了”之后,直接跑路,是会有问题的,因为 B 还没有发起结束,而如果 A 跑路,B 就算发起结束,也得不到回答,B 就不知道该怎么办了。另一种情况是,A 说完“不玩了”,B 直接跑路,也是有问题的,因为 A 不知道 B 是还有事情要处理,还是过一会儿会发送结束

状态时序图

  • 断开的时候,我们可以看到,当 A 说“不玩了”(FIN报文段,FIN标识为1),就进入 FIN_WAIT_1 的状态,B 收到“A 不玩”的消息后,发送知道了,就进入 CLOSE_WAIT 的状态。
  • A 收到“B 说知道了”,就进入 FIN_WAIT_2 的状态,如果这个时候 B 直接跑路,则 A 将永远在这个状态。TCP 协议里面并没有对这个状态的处理,但是 Linux 有,可以调整 tcp_fin_timeout 这个参数,设置一个超时时间。
  • 如果 B 没有跑路,发送了“B 也不玩了”的请求到达 A 时,A 发送“知道 B 也不玩了”的 ACK 后,从 FIN_WAIT_2 状态结束,按说 A 可以跑路了,但是最后的这个 ACK 万一 B 收不到呢?则 B 会重新发一个“B 不玩了”,这个时候 A 已经跑路了的话,B 就再也收不到 ACK 了,因而 TCP 协议要求 A 最后等待一段时间 TIME_WAIT,这个时间要足够长,长到如果 B 没收到 ACK 的话,“B 说不玩了”会重发的,A 会重新发一个 ACK 并且足够时间到达 B。
  • A 直接跑路还有一个问题是,A 的端口就直接空出来了,但是 B 不知道,B 原来发过的很多包很可能还在路上,如果 A 的端口被一个新的应用占用了,这个新的应用会收到上个连接中 B 发过来的包,虽然序列号是重新生成的,但是这里要上一个双保险,防止产生混乱,因而也需要等足够长的时间,等到原来 B 发送的所有的包都死翘翘,再空出端口来。等待的时间设为 2MSL,MSL 是 Maximum Segment Lifetime,报文最大生存时间,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为 TCP 报文基于是 IP 协议的,而 IP 头中有一个 TTL 域,是 IP 数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减 1,当此值为 0 则数据报将被丢弃,同时发送 ICMP 报文通知源主机。协议规定 MSL 为 2 分钟,实际应用中常用的是 30 秒,1 分钟和 2 分钟等。
  • 还有一个异常情况就是,B 超过了 2MSL 的时间,依然没有收到它发的 FIN 的 ACK,怎么办呢?按照 TCP 的原理,B 当然还会重发 FIN,这个时候 A 再收到这个包之后,A 就表示,我已经在这里等了这么长时间了,已经仁至义尽了,之后的我就都不认了,于是就直接发送 RST,B 就知道 A 早就跑了

A发了fin,B收到后会回复两条消息。 第一条是ack,b表示我知道了,但我还有数据需要继续处理。a收到后状态变为fin wait1. 当b处理完后,发了第二条消息fin ack,a收到后状态变为fin wait2。 然后a又发一条ack,a状态变为time wait,如果b顺利接到消息,则b结束,a等一会结束。 顺利的话,a发两条消息,b发两条消息。 不顺利,a为了确保b收到了最后的ack,会等一会包的失效时间,如果b没收到最后的ack,根据tcp机制,b会重复发一遍fin ack,a收到了会再发ack。 最后还有reset保证a告诉b,他a不干了

TCP状态机

在这个图中,加黑加粗的部分,是上面说到的主要流程,其中阿拉伯数字的序号,是连接过程中的顺序,而大写中文数字的序号,是连接断开过程中的顺序。加粗的实线是客户端 A 的状态变迁,加粗的虚线是服务端 B 的状态变迁。

拥塞控制原理

流量控制只能管一条TCP连接的情况,根据接收方windowsize决定该发送多少数据。即使流量控制正确,但网络带宽有限,如果tcp连接过多,超过路由器能力,就会分组丢失。

拥塞控制是针对整个网络,流量控制只针对一条tcp连接。

拥塞的成因和代价

场景1:导致分组延迟 太大

假设路由器无限缓存,λin是发送的数据,λout是接受的数据。当in在C/2前,in和out线性增长,超过C/2,out速度不变,因为路由器来不及转发那么多数据。

超过C/2,分组延迟越来越大。

场景2:降低吞吐量

λin是发送数据速度,λin' 是发送的数据,包含重传分组。λout是接受的数据。

情况a: Sender能够通过某种机制获知路由器buffer信息,有空闲才发 (goodput)

假设链路带宽是R,Sender可以知道路由器的缓存情况,在R/2以前,λout可以和λin'一致,不会丢失分组。但R/2以后,Sender认为路由器没有缓存了,所以发送速度不会超过R/2,为什么R/2以后Sender认为路由器没有缓存了?

情况b: 分组丢失后才重发:λin'>λout。

这种情况sender不知道路由器的缓存情况,所以当速度过快,会丢失分组,当λin'有R/2,λout只有R/3(这是推测数值,只是为了说明λout不能随λin'线性增长),因为λin'包含重发的分组,λout实际接收到数据就量<λin'实际发送出的数据量。

意味着有效吞吐量变低,由于拥塞,导致重发分组,导致吞吐量变低

情况c:分组丢失和定时器超时后都重发, λin'变得更大,可能当λin'有R/2,λout只有R/4(这是推测数值,只是为了说明λout变少了)

场景三:多跳网络,吞吐量更低

多跳网络,从发送方到接收方有多个路由器。 

图里从A-C,D-B会经过同一个路由器。如果第一个路由器成功传输,但在第二个路由器分组丢失,则第一个路由器的传输能力被浪费了。

当λin'变得很大,λout趋近于0,代表网络崩溃了。

拥塞控制的方法

  • 端到端控制,是靠host主机实现,tcp是这种
  • 网络辅助,是得靠主机以外的方法实现

我们看一下拥塞控制的问题,也是通过窗口的大小来控制的,前面的滑动窗口 rwnd 是怕发送方把接收方缓存塞满,而拥塞窗口 cwnd,是怕把网络塞满。

这里有一个公式 LastByteSent - LastByteAcked <= min {cwnd, rwnd} ,是拥塞窗口和滑动窗口共同控制发送的速度。

那发送方怎么判断网络是不是慢呢?这其实是个挺难的事情,因为对于 TCP 协议来讲,他压根不知道整个网络路径都会经历什么,对他来讲就是一个黑盒。

TCP 发送包常被比喻为往一个水管里面灌水,而 TCP 的拥塞控制就是在不堵塞,不丢包的情况下,尽量发挥带宽。

水管有粗细,网络有带宽,也即每秒钟能够发送多少数据;水管有长度,端到端有时延。在理想状态下,水管里面水的量 = 水管粗细 x 水管长度。对于到网络上,通道的容量 = 带宽 × 往返延迟。

如果我们设置发送窗口,使得发送但未确认的包为为通道的容量,就能够撑满整个管道。

如图所示,假设往返时间为 8s,去 4s,回 4s,每秒发送一个包,每个包 1024byte。已经过去了 8s,则 8 个包都发出去了,其中前 4 个包已经到达接收端,但是 ACK 还没有返回,不能算发送成功。5-8 后四个包还在路上,还没被接收。这个时候,整个管道正好撑满,在发送端,已发送未确认的为 8 个包,正好等于带宽,也即每秒发送 1 个包,乘以来回时间 8s。

如果我们在这个基础上再调大窗口,使得单位时间内更多的包可以发送,会出现什么现象呢?

我们来想,原来发送一个包,从一端到达另一端,假设一共经过四个设备,每个设备处理一个包时间耗费 1s,所以到达另一端需要耗费 4s,如果发送的更加快速,则单位时间内,会有更多的包到达这些中间设备,这些设备还是只能每秒处理一个包的话,多出来的包就会被丢弃,这是我们不想看到的。

这个时候,我们可以想其他的办法,例如这个四个设备本来每秒处理一个包,但是我们在这些设备上加缓存,处理不过来的在队列里面排着,这样包就不会丢失,但是缺点是会增加时延,这个缓存的包,4s 肯定到达不了接收端了,如果时延达到一定程度,就会超时重传,也是我们不想看到的。

于是 TCP 的拥塞控制主要来避免两种现象,包丢失和超时重传。一旦出现了这些现象就说明,发送速度太快了,要慢一点。但是一开始我怎么知道速度多快呢,我怎么知道应该把窗口调整到多大呢?

如果我们通过漏斗往瓶子里灌水,我们就知道,不能一桶水一下子倒进去,肯定会溅出来,要一开始慢慢的倒,然后发现总能够倒进去,就可以越倒越快。这叫作慢启动。

一条 TCP 连接开始,cwnd 设置为一个报文段,一次只能发送一个;当收到这一个确认的时候,cwnd 加一,于是一次能够发送两个;当这两个的确认到来的时候,每个确认 cwnd 加一,两个确认 cwnd 加二,于是一次能够发送四个;当这四个的确认到来的时候,每个确认 cwnd 加一,四个确认 cwnd 加四,于是一次能够发送八个。可以看出这是指数性的增长。

涨到什么时候是个头呢?有一个值 ssthresh 为 65535 个字节,当超过这个值的时候,就要小心一点了,不能倒这么快了,可能快满了,再慢下来。每收到一个确认后,cwnd 增加 1/cwnd,我们接着上面的过程来,一次发送八个,当八个确认到来的时候,每个确认增加 1/8,八个确认一共 cwnd 增加 1,于是一次能够发送九个,变成了线性增长。

但是线性增长还是增长,还是越来越多,直到有一天,水满则溢,出现了拥塞,这时候一般就会一下子降低倒水的速度,等待溢出的水慢慢渗下去。拥塞的一种表现形式是丢包,需要超时重传,这个时候,将 sshresh 设为 cwnd/2,将 cwnd 设为 1,重新开始慢启动。这真是一旦超时重传,马上回到解放前。

但是这种方式太激进了,将一个高速的传输速度一下子停了

前面我们讲过快速重传算法。当接收端发现丢了一个中间包的时候,发送三次前一个包的 ACK,于是发送端就会快速地重传,不必等待超时再重传。TCP 认为这种情况不严重,因为大部分没丢,只丢了一小部分,cwnd 减半为 cwnd/2,然后 sshthresh = cwnd,当三个包返回的时候,cwnd = sshthresh + 3,也就是没有一夜回到解放前,而是还在比较高的值,呈线性增长。

就像前面说的一样,正是这种知进退,使得时延很重要的情况下,反而降低了速度。

但是如果你仔细想一下,TCP 的拥塞控制主要来避免的两个现象都是有问题的。

第一个问题是丢包并不代表着通道满了,也可能是管子本来就漏水。例如公网上带宽不满也会丢包,这个时候就认为拥塞了,退缩了,其实是不对的。

第二个问题是 TCP 的拥塞控制要等到将中间设备都填充满了,才发生丢包,从而降低速度,这时候已经晚了。其实 TCP 只要填满管道就可以了,不应该接着填,直到连缓存也填满。

为了优化这两个问题,后来有了 TCP BBR 拥塞算法。它企图找到一个平衡点,就是通过不断地加快发送速度,将管道填满,但是不要填满中间设备的缓存,因为这样时延会增加,在这个平衡点可以很好的达到高带宽和低时延的平衡。

为了优化这两个问题,后来有了 TCP BBR 拥塞算法。它企图找到一个平衡点,就是通过不断地加快发送速度,将管道填满,但是不要填满中间设备的缓存,因为这样时延会增加,在这个平衡点可以很好的达到高带宽和低时延的平衡。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值