TCP传输管理协议

TCP传输管理协议

滑动窗口:TCP是一种面有序的、可靠的、有连接状态的字节流传输协议TCP要保证可靠,需要对每一个数据包进行ACK确认后才能发送下一个数据包,有了滑动窗口,发送端在发送完一个数据包后可以不用等待它的ACK,只要新包的Seq与没有得到确认包的最小seq之差小于滑动窗口大小,就可以继续发送新包,接收端可以在接收了多个包后 只发送一个ACK.

1、TCP数据包格式

  • CWR:表明拥塞窗口已经降低(发送速率减缓了)
  • ECE:ECN回显位,当接收端收到被拥塞路由器标记在IP层的ECN标记包后,发送ACK包会回显ECE标志位以告知发送端网络出现拥塞
  • URG:紧急指针
  • ACK:确认包
  • PSH:表明接受方应该尽快给应用程序传送这个数据(实际没什么用)
  • RST:重置包
  • SYN:同步包
  • FIN:结束连接数据报
  • 窗口大小:用于通告本段缓存的剩余容量(即时能接受的最大数据量)
  • 头部长度:由于头部长度的单位位4字节,所以TCP选项头部必须填充到4字节的倍数位

确认号、ECE、ACK、窗口大小这几栏是由接收端填写的


2、TCP选项

由于头部长度只有4位,且单位为4字节,所以TCP Options的最大长度为40字节(15*4-20)

  • 每个选项的头一个字节位类型值,指明了该选项的类型,后一个字节指明该选项头部的长度(TLV格式)。
  • 不能被理解的选项会被简单地忽略掉

1、 MSS:最大报文段大小:

允许从对方接收到的最大报文段(不包括TCP和IP头部),通讯双方发送数据时,数据包大小必须小于等于对方声明的MSS的大小。MSS一般在SYN包中携带,如果SYN包中没有声明MSS,则默认位536字节(576-20-20)

2、SACK:选择确认选项:

由于滑动窗口的使用,使得发送方可以不用等到ACK继续发送数据,当接收方接受到的数据包序列号不连续时(中途有失序或丢包)SACK用于说明收到的不连续的数据包的序列号值,以便发送方更好的组织重传)

发送方必须在SYN包中携带SACK-Permitted选项,接收端才能使用SACK选项

SACK信息保存在SACK选项中,包含了接收方已经成功接收到的数据块的序列号范围,每一个范围被称为一个SACK块由一对32位的序列号表示,因此如果一个SACK中含有n个SACK块,则SACK选项头长度为(8n+2)(2中1个字节表示SACK选项类型,一个表示SACK选项长度)

3、WSOPT:窗口缩放选项:

TCP固定头中窗口大小为16位,使用窗口缩放选项可以将窗口大小增大为16位~30位,最大容量达到1GB,WSOPT选项只能出现在SYN包中

4、TSOPT:时间戳选项:

发送方在每一个报文段中添加2个4字节的时间戳数值,当发送数据包时,发送方将一个32位的当前时间戳数值填充TSV字段中作为时间戳选项的第一部分,而接收方则将收到的时间戳数值原封不动地抄写在第二部分时间戳回显字段TSER

时间戳的作用:

  • 1、通过时间戳可以测量RTT值(RTT=收到ACK时间-时间戳的发送时间)
  • 2、防止序列号回绕:由于序列号的位数是有限的,当使用完所有的序列号后会重新使用使用过的序列号(如最开始序列号从0开始,当一直到2的16次方-1后,又会从0开始)

5、UTO:用户超时选项:

指明了发送方愿意等待对方的ACK的时长,是一个建议性的行为,接收方可以通过这个时长来调整自己的确认行为,也可以不做参考


3、TCP连接的建立和终止

1、 初始序列号(ISN):

客户端或服务器端最开始建立连接时都会生成一个随机正数来作为初始序列号(为了防止伪造IP来破坏连接,也为了区分不同的连接实例使用不同的初始序列号),系统不同初始序列号生成的函数是不同的。

Linux系统的ISN:半随机的方法,基于时间的,在建立连接时会随机生成一个时间偏移(偏移量时通过基于4元组的加密哈希函数计算出来的),以偏移后的时间值为ISN

2、 TCP半关闭:FIN_WAIT_2状态

  • socket调用shutdown()函数时本端会发送一个FIN包,表示本端已经没有数据待发送,但仍然希望接受对端的数据,直到对端发送FIN包才进入TIME-WAIT状态,如果没有收到对端的FIN本端将一直处于FIN_WAIT_2状态,就称为半关闭状态
  • socket调用close()为常规完全关闭,本端会主动发送一个FIN包,表示本端没有数据要传送也没有数据需要收取,进入FIN_WAIT_2状态会设置一个计时器,当计时器的时间超时时如果连接仍然处于闲置状态,本端将会自动转化为CLOSED状态。Linux系统:变量net.ipv4.tcp_fin_timeout值记录计时器的秒数值,默认为60s

4、TCP状态转换

1、TIME_WAIT状态

  • 当主动关闭连接的那端在收到对端发过来的FIN,发送了最后一个ACK后进入TIME-WAIT状态,
    当两端同时发起关闭连接时,两端发送完最后一个ACK都会进入TIME-WAIT状态
  • TIME-WAIT状态的时长为2倍的MSL时间,之后自动转化为CLOSED状态(MSL(maximum segment lifetime):报文最大生存时间,RFC规定为2m,(OS系统实现有所不同)实际常用30s,1m或2m,Linux默认为30s,可以自行设置参数值)
  • TIME_WAIT存在的目的:1、主动关闭的一端发送最后一个ACK后进入等待状态,当最后一个ACK没有被对端收到时,对端会再次发送FIN直到收到主动关闭方再次发送的ACK为止,所以是为了确保最后一个ACK被对端收到;2、为了保证此次连接发送的所有数据包(延迟到达的)都在网络中消失,不允许下一个连接收到上一个链接的数据包
  • TIME-WAIT状态下的影响:处于TIME-WAIT状态下的连接,该连接在2个MSL时间内仍然没有释放不可以被再次建立四元组完全相同的连接(各系统实现有所不同)Linux系统:处于TIME-WAIT状态的连接端口暂时禁止连接复用(既通过相同的端口号再次发生请求到与上次相同的地址和端口号),但可以使用SO-REUSEADDR选项来强制复用Windows系统:只防止完全匹配(2边端口号和地址)的处于TIME-WAIT状态的出站连接(即主动发连接请求)的建立,而不限制入站连接(即被动回应对方的连
    接)的建立,处于TIME-WAIT状态的终端收到的segment都会丢弃,所以处于TIME-WAIT状态都会超时,需要对端对超时进行处理
    其他系统:采用更严格的限制,处于TIME-WAIT状态的连接的端口会被暂时禁止所有进程使用(其他地址的连接也不可以使用这个端口)直到2倍的MSL时间,当同时有很多个连接处于TIME-WAIT状态时,会同时有多个端口号不能用,造成端口短缺
    由于系统需要分配内存块来记录每个处于TIME_WAIT状态的连接,因此如果系统中存在大量处于TIME_WAIT状态的连接时会使得操作系统的速度严重减缓

安静时间:当处于TIME-WAIT状态的主机崩溃并在2倍MSL时间内重启连接时(为了防止崩溃前延迟的数据干扰新连接)TCP需等待1个MSL的时间才能重启连接,这个时间就叫做安静时间

TIME-WAIT状态暗杀:当处于TIME-WAIT状态的本端收到延迟到达的数据包时会发送一个ACK给对端,对端已经处于CLOSED状态因此会发送一个RST包给本端,本端会过早退出TIME-WAIT状态进入CLOSED状态,这种情况叫做TIME-WAIT暗杀(OS应该阻止TIME-WAIT暗杀如处于TIME-WAIT状态时收到RST包不作出任何反应)


5、TCP连接同时开启与同时关闭

  • 两端同时发起主动连接时,两端都进入syn_rcvd状态

  • 两端同时发起主动关闭时,两边都会进入TIME_WAIT状态等待2MLS时间才进入CLOSED状态

5、TCP重置报文端(RST包)

重置包(Reset Segments):设置了RST位的segments
在TCP连接两端如果收到异常的segment会发送重置包来关闭重置连接,Reset Segment中ACK位必须标识,且ACK码必须落在滑动窗口之内(为了防止重置攻击)收到RST包的一方不需要发送ACK包,发送RST包的那端如有缓存数据,会丢弃缓存区的之前没来得及发出去的包直接发送RST包

发送RST包的几种情况:1、 端口未打开:发送TCP/IP到达对端,但是对端没有程序监听目的端口时,对端会发送一个RST包来重置连接。2、程序没有取读完所有接收的数据就调用soket的close()关闭连接,会发送RST包给对端。3、 超过超时重传次数、网络暂时不可达。4、 超过超时重传次数、网络暂时不可达。5、非正常包,连接已经关闭,seq 不正确等

RST攻击:客户端A与服务端B建立连接,攻击者C通过伪装为A向B发送RST包,如果RST包的ACK码正确(ACK码就是ACK包中的ACK码),B会异常关闭与A的连接,这就成为RST攻击(复位攻击)


6、TCP的PMTUD(最大传输单元发现)

TCP的PMTU处理方法:当连接建立时,发送方从MIN(出站接口的MTU,对端声明的MSS
(未声明时默认为536字节))中的最小值来作为传输单元发送(SMSS),(同一连接不同方
向的传输单元可以是不相同的),当SMSS选定之后,发送的segment会标记DF(不碎片化)
位发送,当收到PTB(包太大信息)时TCP会减小segment的大小重新回传(一般PTB信息
中包括了下一个跳的MTU值)


7、TCP服务器设计

TCP服务器大多都是并发的,当有新的请求到达服务器时,服务器会接受连接并调用一个新的进程或线程(根据OS不同而不同)来处理这个新的连接

TCP服务器入站连接队列(Incoming Connection Queue):

当多个连接包同时到达服务器时,或者服务器繁忙无暇处理到达的连接包时,连接包会分为两种状态分别放入两种不同的连接队列中等待被处理

  1. 连接还没有建立,但是服务器已经收到了SYN包,处于SYN_RCVD状态会被存放在一个队列中等待

    • 当服务器收到SYN包连接请求时,系统会检查处于SYN_RCVD状态的连接数量是否大于参数net.ipv4.tcp_max_syn_backlog的值(默认为1000)如果大于则会拒绝连接悄悄丢弃这个SYN包,
    • 如果处于SYN_RCVD状态的连接数量小于net.ipv4.tcp_max_syn_backlog值,这服务器的tcp组件会回复SYN+ACK包并完成三次握手,(只有完成了三次握手的连接才能被应用程序看到)当应用程序没空处理这个新连接发送的请求时,完成三次握手的新连接请求segment会被存放在另一个队
      里中等待程序处理
    • 如果处于SYN_RCVD状态的连接数量大于net.ipv4.tcp_max_syn_backlog值,在Linux系统中会延缓对这个SYN包的处理(尽可能不丢弃连接),当系统中设置参数net.ipv4.tcp_abort_on_overflow被设置(默认不设置)时,TCP组件会发送一个Reset segment给这个SYN的发送端,连接会被重置(最好不要设置这个参数,因为客户端收到重置包会认为服务器不存在放弃连接而不是服务器太忙,没有收到重置包且应答时间超时时,客户端会再次重传SYN包,这是有可能储存队列已经有位置了,连接就能够被建立)
  2. 三次握手已经完成,连接已经建立,但请求还没有被程序接受会被存放在另一个队列中等待程序处理

    • 每个监听的终端(IP加端口号)都有一个固定长度的队列(队列最大长度
      由参数net.core.somaxconn控制,默认为128)用于储存已经完成三次
      握手但请求仍未被程序接受的连接数据包

TCP服务器的地址与端口号绑定:


8、TCP超时和重传

1、RTO设置

TCP超时:在规定时间RTO内没有收到对端的ACK就叫做超时

RTO:超时重传的时间Retranstmission Timeout

重传二义性:是只数据包没有携带时间戳选项,当开启重传后收到的ACK无法判断是对第一次发送的应带还是对于重传包的应答

RTO设置方法:

超时与RTT有关,如果比RTT早则会不必要的重复,RTO比RTT长太多则会影响网络的吞吐量,由于RTT会随时变化(受到网络中数据包多少的影响),因此RTO需要跟踪RTT的变化作出动态调整

RTT采样的方法:

1、通过TCP拓展头部的Timestamp选项,在Linux(Linux中net.ipv4.tcp_timestamps变量控制是否使用Timestamp,0为不使用,1为使用),Window(TCP323Opts控制Timestamp的使用,0为不使用,2为使用)系统中是默认使用Timestamp选项的
RTT=当前时间-timesatamp中记录的发送时间值,这种更精准。

2、在TCP重传队列中保存着发送而未被确认的数据包,当收到数据包的确认包则该包会从队列中删除,数据包中的TCP控制块包含着一个变量,tcp_skb_cb->when,记录了该数据包的第一次发送时间。RTT=当前时间-第一次发送的时间

RTO算法:
1、经典算法(适用RTT波动较小的情况):

  • SRTT:经过平滑后的RTT的值,每测量一次RTT就对SRTT作一次更新计算

2、标准算法(适合RTT大幅波动的情况):

  • RTO初始值:初次传送SYN包时(RTT还没有采过样)RTO值,一般为1s也有很多系统使用3s,
    当收到第一个确认包就完成了RTTs第一次采样,此时SRTT<—RTTs,RTTVAR<—RTTs/2

  • RTO指数退避:当超时第一次重传后,第二次重传等待时间是第一次的2倍,第三次重传等待时间是第二次的2倍,2为退避因子,直到收到重传数据包的应答,RTO退避因子回复为1,(这样为了当网络处于无法快速交付数据包状态时减小网络负担)

  • 经过重传后收到的应答且没有Timestamp选项头的应该忽略这次传送的RTT采样(因为没有Timestamp不能确定这个确认包是确认第一次传送的那个数据包还是重传的数据包这个叫做重传歧义),只有收到没经过重传的确认包才能作为RTT采样更新SRTT

3、Linux算法:计算方法和Standard Method一样,但是不允许反常的RTTVAR参与计算,且RTTVAR有最小值不低于50毫秒,RTO最小值为200ms,最大值为120s

初始计算:SRTT=RTTs
         RTTVAR=RTTs/2
非初始公式:SRTT=(1-g)SRTT+(g)RTTs
            RTTVAR=max(RTTVAR,50)
            RTO=SRTT+4(RTTVAR)
RTO范围【200ms,120s】

4、当收到失序的数据包时


- ACACK:重复的ACK包
- 收到失序的segment时,接收方发送最近一次收到的未失序的segment的应答包,使用重复的ACK(上一个发送的ACK)+SACK信息将收到的失序的segment ACACK的应答包不作为RTT采样,这样使得RTO的值保持为收到未失序segment时的值,避免RTO更新变小产生不必要的重传
- 当收到延迟到达的失序segment时,接收方发送的ACK的应答码为实际收到的累计数据量,TSER为这个segment的TSV值来更新最新的RTO

2、TCP重传机制

1、基于计时器的超时重传

1、发送端会把被发送的segment放在一个窗口中,等待被确认,没有确认不会从窗口中移走,定时器在重传时间
   到期内,每个片段的位置不变
2 .只有等到ACK收到的时候,变成发送并ACK的片段,才会被从窗口中移走。
3 .如果定时器到期没有收到对应ACK, 就重传这个TCP segment重传之后也没有办法完全保证,数据段一定
   被收到,所以仍然会重置定时器,等待ACK,如果定时器到期还是没收到ACK,继续重传,这个过程重
   传的TCP segment一直留着队列之内。重传等待时间不能发送新的数据包,因此超时重传会降低网络的吞吐量

超时重传分为两种情况:

  1. SYN包或者SYN+ACK包超时重传:当RTO超时后,TCP会重复传送数据包,重复时间为二进制指数退避(下一次重传时间是上一次的2倍),SYN最高重传次数默认是5,由系统变量net.ipv4.tcp_syn_retries控制,SYN+ACK最高重传次数默认是5,由系统变量net.ipv4.tcp_synack_retries控制。当重传等待时间默认超过180秒,则放弃连接。

  2. 其他数据包超时重传:当RTO超时后,TCP会重复传送数据包,重复时间为二进制指数退避(下一次重传时间是上一次的2倍),segment包最高重传次数默认是3(不能小于3次),由系统变量net.ipv4.tcp_retries1控制,当重传等待时间超过默认的100秒,由net.ipv4.tcp_retries2控制,则放弃连接。

二进制指数退避RTO:RTO=γRTO

γ又叫退避因子,为2的指数次,依次是1,2,4,8每增加一次收回

传伽马值是上一次的2倍,直到重传segment的ACK时,γ变为1

2、没有选择应答SACK的快速重传

  • 重复的ACK(Duplicate ACK) :当接收方受到失序的segment 时会复制的最后一个有序数据包时发送的ACK发送,这个ACK就叫做重复的ACK,重复的ACK可以跟一个SACK选项头用于标识失序的数据其实序列号,如果重复的ACK中含有windowsize更新则这个重复ACK不能作为三次启动快速重传的依据

  • 如果收到一个失序的报文段时, TCP需要立刻产生一个复制的未失序时的ACK,目的在于让对方知道收到一个失序的报文,并告诉对方自己希望收到的报文seq,发送方会等待,如果连续收到3个(默认是3个,系统可以设置参数)或3个以上的重复 ACK(duplicate ACK),就被判断这个报文
    丢失了,于是就需要立即重传丢失的数据段,不用等RTO超时

  • 当重复的ACK中有没有SACK 选项时,只能一个一个重传丢失的数据包,系统在重传之前计算总的发送数据量称为恢复点

3、基于选择应答选项SACK的快速重传(Fast Retransmission)

  • 在三次握手时,如果本端收到对端的SYN包中包含SACK-Permitted拓展选项,则本端在收到失序数据包时可以生成SACK(Selective Acknowledge)来指明希望收到缺失的数据包序列号,SACK中每个SACK block占用8个字节,SACK选项类型占用2个字节,SACK一般会与TSOPT(占用10个字节)一起使用,这样一个ACK包中最多能包含3个SACK块((40-12)/8=3)
  • 在SACK信息中,第一个SACK块 记录收到的失序的数据包的首尾序列号,剩下的block重复上一个ACK中SACK块信息,避免上一个ACK遗失造成信息丢失
  • SACK和ACK如果在网路中丢失将不会重传除非ACK中含有数据(或者是设置了SYN或FIN位)
  • 当重复的ACK中有SACK时可以同时重传多个segment

9、虚假超时和虚假重传

虚假RTO超时和虚假重传(Spurious Retransmissions):数据没有丢失的情况下重传

  • DSACK(Duplicate SACK):SACK中的第一个SACK block指明收到的重复数据包的序列号,DSACK信息不在多个SACK中重复,如果ACK遗失则DSACK信息遗失,不具有健壮性

  • 虚假超时重传出现的情况:当最近的RTT明显增长且超过RTO时会出现虚假重传

  • 虚假重传检查算法(detection algorithm):检验重传是否是虚假重传

    1、Eifel检查算法:在重传的segment中设置TSOPT的TSV值,当收到segment的序列号的ACK时,通过TSOPT的TSER时间与重传segmentd的TSV时间比较,如果TSER

10、TCP交互式通讯

TCP数据分为两种:1、大批量数据(如web、文件共享、电子邮件等)通常数据量很大。2、交互式数据(如远程登陆、网络游戏等,每个交互式按键会生成一个单独的数据包,每个按键时独立传输的,每次一个字符生成单独的数据包,而不是一次一行,这里的按键包括输入文字或点击图标)数据量比较小

SMSS:单位时间内发送方能够发送的最大数据量 SMSS=min(MSS,MTU-TCP头-IP头)MSS为接收方声明的最大传输片段值

ACK快速确认:接收端每收到一个数据报就返回一个ACK

ACK延迟确认:许多情况下,tCP并不对每个到来的数据包都及时返回ACK,而是采用TCP的积累ACK字段允许TCP延迟一段时间发送ACK,以便将ACK和相同方向上需要传送的数据结合发送,提高效率,这种捎带传输的方法经常用于批量数据传输(TCP实现ACK延迟应小于500ms,实践中最大延时为200ms,延时太长会造成虚假重传)

基于不同的OS,延迟ACk的最大时延可以动态配置

  • Linux:使用一种动态调节算法(可以在ACK快速确认模式和ACK延迟确认模式直接按动态切换)
  • MacOX:系统变量net.inet.tcp.delayed_ack值设置延时ACk,值=0表示禁止使用延时ACK,值=1始终延时,值=2隔一个包回复一个ACK,值=3自动检测回复时间(默认值为3)
  • 新版Window:TcpAckFrequency表示延时ACK计时器超时前在传ACK数目,值=1表示快速确认,值=2表示延迟确认,变量TcpDelAckTicks控制发送延时ACK前要等待的时间默认值为2以百毫秒为单位

Nagle算法:针对交互式数据包传输
在交互式数据传输中,单个数据包中的有效数据所占的比例很小(IPv4和TCP头部占比很大),在广域网中存在大量的微型数据包会加重拥塞,严重影响网路性能。

  • Nagle算法:当一个TCP连接中有已经发送但未经确认的数据时,小的报文段(长度小于SMSS)就不能被发送,必须等到所有在传数据都收到ACK,并且在收到ACK后,TCP需要收集这些小数据将其整合到一个报文段中发送。
  • Nagle算法遵循(stop-and-wait)规程:收到所有在传数据的ACK后才能继续发送,这种算法的好处在于实现了传输速率的自我控制,ACK返回越快,数据传输也越快,RTT控制者发包速率

当Nagle算法于延时ACK相结合时会导致某一短暂的死锁,降低网络效率

Nagle算法的禁用情况:

    1、禁止与延时ACK结合
    2、对于那些要求延时尽量小的应用(如远程控制中的鼠标或按键操作需要即使送达的快捷返回,
       网络游戏等)不能使用Nagle算法

11、TCP流控制与拥塞控制

1、流量控制与窗口管理

1、发送方滑动窗口


- 提供窗口(SND.WND):由接收端在ACK中通告的大小
- 可用窗口(SND.NXT):发送方通过接收端发送的ACK中提供窗口的大小减去在传未确认数据
- 滑动窗口关闭:窗口左边界右移,当已发送数据得到ACK确认时,窗口会减小
- 滑动窗口打开:窗口右边界右移,使得可发送数据量增大,当已确认数据得到处理,接收端可用缓存变大,窗口也自然变大
- 滑动窗口向右滑动:窗口大小不变,左边界和右边界整体向右移动。在传数据得到确认同时接收端读取了已确认的数据

2、接收端滑动窗口

  • 到达数据包序列号小于左边界RCV.NXT,则被认为是重复的数据包而被丢弃
  • 到达数据包序列号大于右边界RCV.NXT+RCV.WND,则被认为超出处理范围而被丢弃
  • 达到数据包序列号只有落在接收窗口内才能被存储起来。注意由于TCP的ACK的积累结构窗口内的其他报文端也可以被接收确认,只有当收到的数据包序列号等于左边界RCV.NXT时,接收窗口才能向右滑动。

3、零窗口与持续计时器

  • 零窗口:即发送窗口左右边界相等时,(接收窗口已经内有内存来存储到来的数据)称为零窗口,此时发送方不能再发送数据
  • 当接收端存储数据被上层应用取读,接收端窗口重新获得可用空间时,会给发送端传输一个窗口更新(window update)的纯ACK,(由于纯ACK如果丢失不会引发重传,双方会进入无限等待的死锁状态)为了防止死锁,TCP发送方会开启一个持续计时器间歇性地查询接收端窗口是否已增长,持续计时器会引发窗口探测(window probe)数据报的传输,要求接收端返回包含窗口大小的ACK(一般在一个RTO之后发送第一个窗口探测包(包含一个字节的数据),随后以指数退避间隔发送)

4、糊涂窗口综合症SWS

当窗口通告较小时,发送端会立刻发送微型数据包填满该窗口,这样在连接中就会出现大量搞消耗的小数据包,这种现象被称为糊涂窗口综合症SWS

避免SWS遵循的原则:

  1、对于接收端,不应该通告小的窗口值,在窗口增至一个全长报文(SMSS)或接收端缓存空间的一半
    (取两者之间最小值)之前,不能通告比当前窗口大的窗口值
  2、对于发送端,不应发送小的报文段,只有满足以下条件之一才能传输报文段:
     a、全长(SMSS)报文端可以发送。
     b、数据段长度>接收端通告过的最大窗口值的一半的可以发送。
     c、没有在传数据的时候可以发送报文段。
     d、该连接禁用Nagle算法时可以发送

2、TCP拥塞控制

ACK时钟和自同步:在高效传输的稳定状态下,TCP双边传输通道都不会出现包堵塞情况,也不会有较大的传输间隔。发送方接到一个ACK就表示网络中能容纳一个新数据包。这种由一个ACK到达(称作ACK时钟)触发一个新数据包传输的关系称为自同步。自同步是网络实现最大吞吐量的状态

1、TCP拥塞检查

对于TCP发送方来说,没有一个精确的方法去知晓中间路由器的状态,推断是否出现拥塞通常看是否有丢包的情况发生,丢包也用作衡量是否实施响应的响应措施的依据

显示拥塞通知ECN和测量延迟,能在丢包发生前检测拥塞。有限网络中路由器和交换机的拥塞是造成丢包的主要原因,而无线网络中传输错误和接收错误是丢包的重要因素,需要判断丢包的真正归因。

2、拥塞窗口

网络传输效率有两方面制约 1.接收端接收窗口的大小(即接收端通知窗口cwnd)。2、网络传输能力(cwnd)
拥塞窗口:反映网络传输能力的变量称为拥塞窗口(即网络中可传输的待发数据量的大小)

  • 拥塞窗口的初始值:当一个新TCP连接之初,还无法获知可用的传输资源,拥塞窗口的初始值也无法确定,获得cwnd的唯一方法是以越来越快的速率不断发送数据,直到出现丢包为止,由于多个TCP共享一个网络资源,以全速启动会影响其他连接的传输性能,所以会有特定的算法来避免过快启动

3、慢启动

慢启动目的:是TCP在用拥塞避免探寻更多可用宽带之前得到拥塞窗口的值,以及帮助TCP建立自同步状态

慢启动启用状态:

1、当一个新的TCP连接建立时
2、检测到丢包(即重传超时RTO)
3、TCP发送端长时间处于空间状态在传输时调用慢启动算法,称为慢启动的再次启动SSR,可以关闭

初始窗口IW:慢启动时第一次发送数据量(即三次握手后,发送方第一次发送的数据量)

  • 当IW=1*SMSS时
  • 延时ACK模式下的慢启动,由于ACK会延时到达因此会减缓cwnd的增加速率,所以需要在慢启动时启用快速确认ACK模式,等到慢启动结束后再启动ACK延时模式

4、拥塞避免

慢启动阈值ssthrest:慢启动阶段,发送窗口呈指数增长,当窗口值达到阈值临界点后网络会出现拥塞丢包情况,从而破坏网络稳定性,这个值就是慢启动的阈值,一旦拥塞窗口值达到慢启动阈值,窗口增长进入拥塞避免算法

  • 采用延时ACK时拥塞避免增幅更小

5、慢启动和拥塞避免算法的选择

6、Tahoe算法和Reno算法

Tahoe算法:连接之初处于慢启动阶段,如检测到丢包,不论述超时重传还是快速重传都会重新进入慢启动状态,丢包时cwnd将减为初始值IW以达到慢启动的目的,直到cwnd=ssthrest(这中算法会降低宽带的利用率)

Reno算法:快速恢复算法,当出现丢包重传,如果是快速重传,则 sshrest = min(cwnd/2,2*SMSS),cwnd=ssthresh,并再每收到一个重复的ACK,cwnd临时增加1个SMSS这样拥塞窗口会再一段时间内急速增长,直到接收到一个不重复的ACK,快速回复结束(这种算法由不足,如果丢失的包不止一个,则会提前退出快速恢复阶段)

NewReno算法:对Reno算法的改进。当首都奥三个重复的ACK引发快速重传时,记录下重传前发送数据的最大序列号(称为恢复点),当且仅当接收到的ACK确认好>恢复点的ACK,才停止快速恢复阶段,(这样可以减少超时重传的发生)

3、标准TCP拥塞管理——基于丢包的拥塞控制算法

1、标准TCP拥塞控制算法

1、连接之初采用慢启动算法(cwnd=IW),ssthrest通常设为一个较大值(至少为awnd)
2、当接收到一个好的ACK时,cwnd会相应更新

   cwnd=cwnd+SMSS (当cwnd

3、当收到三次重复的ACK启动快速重传时,进入快速恢复阶段(Reno快速恢复算法)

   ssthrest= max(cwnd/2,2*SMSS)
   启动快速重传,进入快速回复设置cwnd =ssthrest + 3*SMSS
   每收到一个重复的ACK,cwnd=cwnd+1

4、当收到一个好的不重复的ACK时,设置cwnd=ssthresh,进入拥塞避免阶段
cwnd=cwnd +(1/k)SMSS

5、当发送方长时间处于空闲状态(或出现超时重传)
设置cwnd=RW(重启窗口) RW= min(IW , cwnd)并重启启动慢启动算法

2、对标准TCP拥塞控制的改进

采用选择确认SACK机制的TCP拥塞控制:

  • 当TCP采用SACK时 ,发送方可以同时重传多个丢失的数据包,然而这样做可能会较短的时间内向网络中注入大量的数据,削弱拥塞控制的效果,因此,除了维护窗口,TCP还负责记录注入网络中数据量称为管道(Pipe)变量,若awnd(通知窗口)较大时,只要cwnd-pipe>SMSS,则再任何时候TCP均可发送数据包

转发确认(FACK)和速率减半:

  • 转发确认FACK;在丢包后,当快速重传结束后cwnd值减小,在TCP发送新数据之前至少可以接收一半已经发送数据返回的ACK,这样TCP发送端在前一半RTT时间内处于等待状态,后一半RTT才能发送新数据,为避免出现等待空闲而又不违背将拥塞窗口减半的做法,提出的FACK策略,包含速率减半算法
  • 速率减半算法RHPR:在一个RTT时间内,每接收两个重复的ACK,TCP发送方可发送一个新数据包(在发现丢包后使cwnd逐步而不是快速减半)

限制传输:

  • 快速重传收到三次重复的ACK,在窗口较小的情况下,当出现丢包,网络中可能没有足够的包去引发快速重传和快速恢复机制,限制传输策略规定TCP发送法每接收两个连续的重复ACK,就能发送一个新的数据包,使得网络中由足够多的数据包能触发快速重传,TCP也可以避免长时间等待RTO引发超时重传导致吞吐量下降

拥塞窗口校验CWV
发送端可能在一段时间内停止发送(由于没有新数据需要发送或者其他原因阻止发送),之前的cwnd可能已经无法准确反映当前网络的拥塞状况,因此需要拥塞窗口检验机制CWV

CWV分为两种情况

  • 由于没有新数据需要发送的空闲时长超过一个RTO,则
    更新ssthrest = max (ssthrest , 3/4*cwnd)
    每经过一个RTT空闲时间,cwnd=max( cwnd/2,SMSS)
  • 对于应该发送数据但由于其他原因受限情况
    已使用的窗口大小记录 W_used
    更新ssthrest = max (ssthrest , 3/4*SMSS)
    cwnd = (cwnd+w_used)/2
  • 在长时间暂停发送后,发送方会进入重新启动慢启动阶段,Linux实现了CWV并默认启用

**本地拥塞:**CP产生数据包的速率>链路层发送速率,发送缓存队列占满后出现的丢包

拥塞窗口缩减CWR:
更新ssthrest = cwnd/2
更新cwnd = min (cwnd , 在外数据值+1)
在CWR阶段,每接收2个ACK就将cwnd减1,直到cwnd达到新的ssthrest值或则由于其他原因CWR提前结束(出现丢包)

以下情况满足一个就可以实行拥塞窗口减半CWR

  • 出现本地拥塞

  • 发送端接收到ECE标志的ACK时进入CWR算法

延伸ACK:一个ACK确认两个SMSS以上长度的数据时称为延伸ACK(可能由于ACK的丢失形成的)
当处于CWR阶段,收到延伸ACK时,调整cwnd = 在外数据值+1

缓存区膨胀:

网络设备中包含的大量的内存和包缓冲区会导致TCP协议性能下降,称为缓存区膨胀。主要存在于家用网关的上行端和家用或办公室的接入点处称为最后一米,与排队等待而产生的大量延迟有关。标准TCP协议的拥塞控制算法会在链路瓶颈处将缓存区填满,丢包信息需要很长时间才能反馈到发送端。大量缓存数据使得TCP协议性能下降

积极队列管理和ECN
- 积极队列管理AQW:指路由器或交换机能够积极的将拥塞状况反馈给两端的队列管理策略
- 显示拥塞通知ECN:发生拥塞时,对经过拥塞路由器的数据包在IP头上标记ECN标志。当数据包被接收时,TCP接收方就能直到数据包经过了发生拥塞的路由器。(ECN是在IP层面上操作的,也可以应用于其他传输协议,TCP接收端接收到ECN标记的数据包后,会将每一个ACK数据包ECN回显(即ECE)字段标记,直到接收到发送端发来的CWR标记的数据包,TCP发送端收到ECE标记的ACK时,会与探测到单个丢包时一样调整cwnd值,同时设置新数据包的CWR字段)

若拥塞情况不会持续很长时间,路由器将不会标记ECN标志,因为即使是一个单独的ECN标志,
传输协议也会做出很大的反应

ECN功能的使用需要被激活,且经过的路由器或交换机需要支持AQW功能

4、基于延迟的拥塞控制算法

在没有丢包的情况下,通过不断增长的RTT值来作为拥塞形成的信号

基于延迟的拥塞控制算法具有更好的录用率,更小的丢包率,更快的收敛性和更好的公平性和稳定性

1、vegas算法

先估算一定时间内网络能够传输的数据量,然后与实际传输能力进行比较,若本该传输的数据并没由得到传递,情况持续发生,那么vegas发送端将降低发送速率

在拥塞避免阶段,vegas算法测量每一个RTT中传输的数据量,并将这个数除以网络中观测到的最小RTT,值维持在(α,β)之间,如果<α则增大cwnd,若>β则减小cwnd

  • vegasTCP连接之间平等共用一条链路
  • vegasTCP与标准TCP共用一条链路时,标准TCP会抢占网络资源,当标准TCP发送数据包时,vegasTCP会发现延迟增大而降低发送速率,最终导致对标准TCP占用更多资源
  • Linux系统支持Vegas,但不是默认开启的

2、FAST算法

与vegas算法相似,不同在于:会使用速率起搏技术,每隔一个RTT都会更新发送率,若检测延迟远小于阈值,窗口会进行较快增大,一段时间后再恢复平缓增加,当延迟增大时则相反(这种算法适合处理大带宽延迟的高速网络环境下的拥塞问题)

3、TCP Westwood算法和Westwood+算法

算法与vegas相似,不同在于:会估量连接网络的预期速率,根据ACK的到达动态可变的间隔测量实际发送速率,当拥塞不明显时,测量间隔会比较小,反之亦然。当检测到丢包时,TCP Westwood不会将cwnd减半,而是估计一个值,并将该值作为ssthresh值。在慢启动状态时,使用一种灵活的探测机制适当反复设置ssthresh的值
Linux可以通过加载TCPW块来启动westwood算法

5、复合TCP(CTCP):标准TCP与Vegas算法相结合,既可以根据丢包来进行窗口调整也可以依据延迟来控制拥塞

  • 为了协调两种拥塞控制算法,CTCP定义了一个新的窗口变量:延迟窗口dwnd
  • 发送方可用窗口 W = min (cwnd+dwnd , awnd)
  • CTCP连接之初采用传统的慢启动算法,dwnd值的控制是基于vegas算法,只有在拥塞避免阶段dwnd值才是非零值,通过公式计算得到
  • 在拥塞避免阶段,当ACK到达时 cwnd = cwnd +1/(cwnd+dwnd)
  • CTCP在window中不是默认开启的,Linux也不是默认开启的需要通过加载CTCP模块来启动它

5、TCP友好性

在传输路径中经常会出现几个TCP连接共享一个或多个路由的情况,他们并非均匀地共享带宽资源,而是根据其他连接动态调节分配,但也会出现使用不同设置的TCP连接竞争带宽

为了防止多个TCP对传输资源的恶性竞争,实现更高的带宽利用率,tcp采用了吞吐率限制,使用与流媒体这种大传输量的应用

6、TCP保活机制(keepalive)

  • 保活机制:在不影响数据流内容的情况下探测对方的方式。它是由一个保活计时器实现的,当计时器被激发,连接一端将发送一个保活探测报文(包含1字节数据),对端收到报文会发送一个ACK作为回应。保活机制并不是TCP规范中的一部分。
  • 保活探测报文:一个空报文段(或者只含一个字节),其序列号等于等于对方发送ACK最大确认号+1,响应保活探测的ACK为纯ACK,丢失不会重传。
  • 保活时间(keepalive time):tCP两端在保活时间内连续处于非活动状态,开启保活功能的一段想对端发送一个保活探测报文。如果发送端没有收到响应报文,那么经过一个已经提前配置好的保活时间间隔,将继续发送保活探测报文,直到发送探测报文的次数达到保活探测数(keepalive probe),这时对方主机被确认不可到达,连接将中断
  • 保活探测数:能发送的保活探测报文的最大次数

  • 保活机制的优缺点

    优点:1、有助于服务器决定是否为客户端绑定资源,有助于服务器与非交互性客户进行相对短时间的对话
         2、TCP长时间连接时,如果TCP空间时间过长,大部分NAT映射会话包含超时机制,当连续一段时
            间处于非活动状态时,路由器将删除映射会话,为了避免这种情况发生,启动TCP保活功能
    缺点:1、在出现短暂的网络错误时,保活机制会使一个好的TCP连接断开
         2、保活机制会占用不必要的带宽
    
  • 处于以下几种状态时,保活机制的应对策略

    1、对方主机仍在工作,对方TCP响应正常,请求端将重置保活计时器,若计时器超时之间由应用程序
       通过该连接传输数据,计时器将再次被设定为保活时间值
    2、对方主机崩溃(关闭或正在重启),对方TCP无法响应,请求段会在保活计时器超时后,在保活时间间
       隔不断向对方发送保活探测报文,若指定次数后还没有响应,则断开接,请求端应用层收到“连接超时”
       的差错报告
    3、对方主机崩溃并已经重启,对方会恢复一个RST包来响应,请求段收到后会断开连接,请求端
       的应用层收到“连接被对方重置”的差错报告
    4、对方主机仍在工作,但由于某种原因响应不能到达请求段(网络无法传输),与状态2 的操作一
       样,请求端应用层收到“连接超时”或其他的差错报告
    5、对方主机正常关机,关机时会发送FIN包来关闭连接,因此请求段也会正常发送FIN关闭连接
    

TCP保活机制时在TCP层完成的,上层应用程序不会察觉到,但在上面2、3、4非正常情况时,请求段的应用层将收到一个来自TCP层的差错报告

  • 各系统中控制保活机制参数的变量

    Linux:   
            net.ipv4.tcp_keepalive_time     保活探测时间(默认为7200秒(2小时))
            net.ipv4.tcp_keepalive_intvl    探测时间间隔(默认75秒)
            net.ipv4.tcp_keepalive_probes   保活探测次数(默认为9次)
    Window:
            keepalivetime       保活探测时间 (默认为72000秒)
            keepaliveInterval   探测时间间隔(默认为1秒)
            keepaliveProbes     探测次数(默认为10次)
    

7、tcp/udp端口号分段

  • 0~1023公认端口(well-known port):通常绑定了系统自带的服务(如http端口80,FTP端口21)
  • 1024~49151注册端口(registered port):松散的绑定了某些服务
  • 49152~65535动态临时端口(dynamicand port):客户端使用的临时端口,不应该绑定服务

你可能感兴趣的:(tcp\ip)