TCP传输管理协议
滑动窗口:TCP是一种面有序的、可靠的、有连接状态的字节流传输协议TCP要保证可靠,需要对每一个数据包进行ACK确认后才能发送下一个数据包,有了滑动窗口,发送端在发送完一个数据包后可以不用等待它的ACK,只要新包的Seq与没有得到确认包的最小seq之差小于滑动窗口大小,就可以继续发送新包,接收端可以在接收了多个包后 只发送一个ACK.
确认号、ECE、ACK、窗口大小这几栏是由接收端填写的
由于头部长度只有4位,且单位为4字节,所以TCP Options的最大长度为40字节(15*4-20)
允许从对方接收到的最大报文段(不包括TCP和IP头部),通讯双方发送数据时,数据包大小必须小于等于对方声明的MSS的大小。MSS一般在SYN包中携带,如果SYN包中没有声明MSS,则默认位536字节(576-20-20)
由于滑动窗口的使用,使得发送方可以不用等到ACK继续发送数据,当接收方接受到的数据包序列号不连续时(中途有失序或丢包)SACK用于说明收到的不连续的数据包的序列号值,以便发送方更好的组织重传)
发送方必须在SYN包中携带SACK-Permitted选项,接收端才能使用SACK选项
SACK信息保存在SACK选项中,包含了接收方已经成功接收到的数据块的序列号范围,每一个范围被称为一个SACK块由一对32位的序列号表示,因此如果一个SACK中含有n个SACK块,则SACK选项头长度为(8n+2)(2中1个字节表示SACK选项类型,一个表示SACK选项长度)
TCP固定头中窗口大小为16位,使用窗口缩放选项可以将窗口大小增大为16位~30位,最大容量达到1GB,WSOPT选项只能出现在SYN包中
发送方在每一个报文段中添加2个4字节的时间戳数值,当发送数据包时,发送方将一个32位的当前时间戳数值填充TSV字段中作为时间戳选项的第一部分,而接收方则将收到的时间戳数值原封不动地抄写在第二部分时间戳回显字段TSER
时间戳的作用:
指明了发送方愿意等待对方的ACK的时长,是一个建议性的行为,接收方可以通过这个时长来调整自己的确认行为,也可以不做参考
客户端或服务器端最开始建立连接时都会生成一个随机正数来作为初始序列号(为了防止伪造IP来破坏连接,也为了区分不同的连接实例使用不同的初始序列号),系统不同初始序列号生成的函数是不同的。
Linux系统的ISN:半随机的方法,基于时间的,在建立连接时会随机生成一个时间偏移(偏移量时通过基于4元组的加密哈希函数计算出来的),以偏移后的时间值为ISN
安静时间:当处于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包不作出任何反应)
重置包(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攻击(复位攻击)
TCP的PMTU处理方法:当连接建立时,发送方从MIN(出站接口的MTU,对端声明的MSS
(未声明时默认为536字节))中的最小值来作为传输单元发送(SMSS),(同一连接不同方
向的传输单元可以是不相同的),当SMSS选定之后,发送的segment会标记DF(不碎片化)
位发送,当收到PTB(包太大信息)时TCP会减小segment的大小重新回传(一般PTB信息
中包括了下一个跳的MTU值)
TCP服务器大多都是并发的,当有新的请求到达服务器时,服务器会接受连接并调用一个新的进程或线程(根据OS不同而不同)来处理这个新的连接
当多个连接包同时到达服务器时,或者服务器繁忙无暇处理到达的连接包时,连接包会分为两种状态分别放入两种不同的连接队列中等待被处理
连接还没有建立,但是服务器已经收到了SYN包,处于SYN_RCVD状态会被存放在一个队列中等待
三次握手已经完成,连接已经建立,但请求还没有被程序接受会被存放在另一个队列中等待程序处理
TCP服务器的地址与端口号绑定:
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波动较小的情况):
2、标准算法(适合RTT大幅波动的情况):
RTO初始值:初次传送SYN包时(RTT还没有采过样)RTO值,一般为1s也有很多系统使用3s,
当收到第一个确认包就完成了RTTs第一次采样,此时SRTT<—RTTs,RTTVAR<—RTTs/2
RTO指数退避:当超时第一次重传后,第二次重传等待时间是第一次的2倍,第三次重传等待时间是第二次的2倍,2为退避因子,直到收到重传数据包的应答,RTO退避因子回复为1,(这样为了当网络处于无法快速交付数据包状态时减小网络负担)
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
1、发送端会把被发送的segment放在一个窗口中,等待被确认,没有确认不会从窗口中移走,定时器在重传时间
到期内,每个片段的位置不变
2 .只有等到ACK收到的时候,变成发送并ACK的片段,才会被从窗口中移走。
3 .如果定时器到期没有收到对应ACK, 就重传这个TCP segment重传之后也没有办法完全保证,数据段一定
被收到,所以仍然会重置定时器,等待ACK,如果定时器到期还是没收到ACK,继续重传,这个过程重
传的TCP segment一直留着队列之内。重传等待时间不能发送新的数据包,因此超时重传会降低网络的吞吐量
超时重传分为两种情况:
SYN包或者SYN+ACK包超时重传:当RTO超时后,TCP会重复传送数据包,重复时间为二进制指数退避(下一次重传时间是上一次的2倍),SYN最高重传次数默认是5,由系统变量net.ipv4.tcp_syn_retries控制,SYN+ACK最高重传次数默认是5,由系统变量net.ipv4.tcp_synack_retries控制。当重传等待时间默认超过180秒,则放弃连接。
其他数据包超时重传:当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
重复的ACK(Duplicate ACK) :当接收方受到失序的segment 时会复制的最后一个有序数据包时发送的ACK发送,这个ACK就叫做重复的ACK,重复的ACK可以跟一个SACK选项头用于标识失序的数据其实序列号,如果重复的ACK中含有windowsize更新则这个重复ACK不能作为三次启动快速重传的依据
如果收到一个失序的报文段时, TCP需要立刻产生一个复制的未失序时的ACK,目的在于让对方知道收到一个失序的报文,并告诉对方自己希望收到的报文seq,发送方会等待,如果连续收到3个(默认是3个,系统可以设置参数)或3个以上的重复 ACK(duplicate ACK),就被判断这个报文
丢失了,于是就需要立即重传丢失的数据段,不用等RTO超时
虚假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
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的最大时延可以动态配置
Nagle算法:针对交互式数据包传输
在交互式数据传输中,单个数据包中的有效数据所占的比例很小(IPv4和TCP头部占比很大),在广域网中存在大量的微型数据包会加重拥塞,严重影响网路性能。
当Nagle算法于延时ACK相结合时会导致某一短暂的死锁,降低网络效率
Nagle算法的禁用情况:
1、禁止与延时ACK结合
2、对于那些要求延时尽量小的应用(如远程控制中的鼠标或按键操作需要即使送达的快捷返回,
网络游戏等)不能使用Nagle算法
- 提供窗口(SND.WND):由接收端在ACK中通告的大小
- 可用窗口(SND.NXT):发送方通过接收端发送的ACK中提供窗口的大小减去在传未确认数据
- 滑动窗口关闭:窗口左边界右移,当已发送数据得到ACK确认时,窗口会减小
- 滑动窗口打开:窗口右边界右移,使得可发送数据量增大,当已确认数据得到处理,接收端可用缓存变大,窗口也自然变大
- 滑动窗口向右滑动:窗口大小不变,左边界和右边界整体向右移动。在传数据得到确认同时接收端读取了已确认的数据
当窗口通告较小时,发送端会立刻发送微型数据包填满该窗口,这样在连接中就会出现大量搞消耗的小数据包,这种现象被称为糊涂窗口综合症SWS
避免SWS遵循的原则:
1、对于接收端,不应该通告小的窗口值,在窗口增至一个全长报文(SMSS)或接收端缓存空间的一半
(取两者之间最小值)之前,不能通告比当前窗口大的窗口值
2、对于发送端,不应发送小的报文段,只有满足以下条件之一才能传输报文段:
a、全长(SMSS)报文端可以发送。
b、数据段长度>接收端通告过的最大窗口值的一半的可以发送。
c、没有在传数据的时候可以发送报文段。
d、该连接禁用Nagle算法时可以发送
ACK时钟和自同步:在高效传输的稳定状态下,TCP双边传输通道都不会出现包堵塞情况,也不会有较大的传输间隔。发送方接到一个ACK就表示网络中能容纳一个新数据包。这种由一个ACK到达(称作ACK时钟)触发一个新数据包传输的关系称为自同步。自同步是网络实现最大吞吐量的状态
对于TCP发送方来说,没有一个精确的方法去知晓中间路由器的状态,推断是否出现拥塞通常看是否有丢包的情况发生,丢包也用作衡量是否实施响应的响应措施的依据
显示拥塞通知ECN和测量延迟,能在丢包发生前检测拥塞。有限网络中路由器和交换机的拥塞是造成丢包的主要原因,而无线网络中传输错误和接收错误是丢包的重要因素,需要判断丢包的真正归因。
网络传输效率有两方面制约 1.接收端接收窗口的大小(即接收端通知窗口cwnd)。2、网络传输能力(cwnd)
拥塞窗口:反映网络传输能力的变量称为拥塞窗口(即网络中可传输的待发数据量的大小)
慢启动目的:是TCP在用拥塞避免探寻更多可用宽带之前得到拥塞窗口的值,以及帮助TCP建立自同步状态
慢启动启用状态:
1、当一个新的TCP连接建立时
2、检测到丢包(即重传超时RTO)
3、TCP发送端长时间处于空间状态在传输时调用慢启动算法,称为慢启动的再次启动SSR,可以关闭
初始窗口IW:慢启动时第一次发送数据量(即三次握手后,发送方第一次发送的数据量)
慢启动阈值ssthrest:慢启动阶段,发送窗口呈指数增长,当窗口值达到阈值临界点后网络会出现拥塞丢包情况,从而破坏网络稳定性,这个值就是慢启动的阈值,一旦拥塞窗口值达到慢启动阈值,窗口增长进入拥塞避免算法
Tahoe算法:连接之初处于慢启动阶段,如检测到丢包,不论述超时重传还是快速重传都会重新进入慢启动状态,丢包时cwnd将减为初始值IW以达到慢启动的目的,直到cwnd=ssthrest(这中算法会降低宽带的利用率)
Reno算法:快速恢复算法,当出现丢包重传,如果是快速重传,则 sshrest = min(cwnd/2,2*SMSS),cwnd=ssthresh,并再每收到一个重复的ACK,cwnd临时增加1个SMSS这样拥塞窗口会再一段时间内急速增长,直到接收到一个不重复的ACK,快速回复结束(这种算法由不足,如果丢失的包不止一个,则会提前退出快速恢复阶段)
NewReno算法:对Reno算法的改进。当首都奥三个重复的ACK引发快速重传时,记录下重传前发送数据的最大序列号(称为恢复点),当且仅当接收到的ACK确认好>恢复点的ACK,才停止快速恢复阶段,(这样可以减少超时重传的发生)
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)并重启启动慢启动算法
采用选择确认SACK机制的TCP拥塞控制:
转发确认(FACK)和速率减半:
限制传输:
拥塞窗口校验CWV
发送端可能在一段时间内停止发送(由于没有新数据需要发送或者其他原因阻止发送),之前的cwnd可能已经无法准确反映当前网络的拥塞状况,因此需要拥塞窗口检验机制CWV
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功能
在没有丢包的情况下,通过不断增长的RTT值来作为拥塞形成的信号
基于延迟的拥塞控制算法具有更好的录用率,更小的丢包率,更快的收敛性和更好的公平性和稳定性
先估算一定时间内网络能够传输的数据量,然后与实际传输能力进行比较,若本该传输的数据并没由得到传递,情况持续发生,那么vegas发送端将降低发送速率
在拥塞避免阶段,vegas算法测量每一个RTT中传输的数据量,并将这个数除以网络中观测到的最小RTT,值维持在(α,β)之间,如果<α则增大cwnd,若>β则减小cwnd
与vegas算法相似,不同在于:会使用速率起搏技术,每隔一个RTT都会更新发送率,若检测延迟远小于阈值,窗口会进行较快增大,一段时间后再恢复平缓增加,当延迟增大时则相反(这种算法适合处理大带宽延迟的高速网络环境下的拥塞问题)
算法与vegas相似,不同在于:会估量连接网络的预期速率,根据ACK的到达动态可变的间隔测量实际发送速率,当拥塞不明显时,测量间隔会比较小,反之亦然。当检测到丢包时,TCP Westwood不会将cwnd减半,而是估计一个值,并将该值作为ssthresh值。在慢启动状态时,使用一种灵活的探测机制适当反复设置ssthresh的值
Linux可以通过加载TCPW块来启动westwood算法
在传输路径中经常会出现几个TCP连接共享一个或多个路由的情况,他们并非均匀地共享带宽资源,而是根据其他连接动态调节分配,但也会出现使用不同设置的TCP连接竞争带宽
为了防止多个TCP对传输资源的恶性竞争,实现更高的带宽利用率,tcp采用了吞吐率限制,使用与流媒体这种大传输量的应用
保活探测数:能发送的保活探测报文的最大次数
保活机制的优缺点
优点: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次)