TCP选项详解

来源:互联网 发布:阿里巴巴数据 编辑:程序博客网 时间:2024/06/05 06:36
窗口扩大因子TCP Window Scale Option (WSopt)
1.前言 
TCP窗口缩放选项是用来增加TCP接收窗口的大小而超过65536字节。这个TCP选项以及其他的几个选项在RFC1323(处理长肥管道网络,LFN)中定义。 
窗口缩放因子对于BDP大于64KB的时候的数据传输的效率非常有用。例如,如果一个T1传输链路,1.5Mbps是通过卫星的链路,RTT时间是513ms,那么BDP是:1500000*.513 = 769,500位或者96,188字节。最大的64KB窗口仅仅允许填充链路缓冲区的68%或者是1.02Mbps。通过使用窗口扩大因子,文件传输可以接近 1.5Mbps,而充分利用可用带宽。这个选现在慢速网络上发送大于64KB的文件也是有用的。通过使用窗口扩大因子,接收窗口可能增加到最大1GB。 
2.选项格式 
RFC 1323中关于窗口扩大选项的图示如下: 
       TCP Window Scale Option (WSopt):   Kind: 3 Length: 3 bytes 
                 +---------+---------+-------------+ 
                 | Kind=3 |Length=3 | shift.cnt     | 
                 +---------+---------+-------------+ 
3.工作过程 
①要启用窗口扩大选项,通讯双方必须在各自的SYN报文中发送这个选项。主动建立连接的一方在SYN报文中发送这个选项;而被动建立连接的一方只有在收到带窗口扩大选项的SYN报文之后才能发送这个选项。 


②这个选项只在一个SYN报文中有意义(<SYN>或<SYN,ACK>),包含窗口扩大选项的报文如果没有SYN位,则会被忽略掉。当连接建立起来后,在每个方向的扩大因子是固定的。注意:在SYN报文本身的窗口字段始终不做任何的扩大(The Window field in a SYN (i.e., a <SYN> or <SYN,ACK>) segment itself is never scaled.)。 


③在启用窗口扩大选项的情况下,若发送一个窗口通告,要将实际窗口大小右移shift.cnt位,然后赋给TCP首部中的16bit窗口值;而当接收到一个窗口通告时,则将TCP首部中的16bit窗口值左移shift.cnt位,以获得实际的通告窗口大小。 


④shift.cnt取值范围为0~14,即最大TCP序号限定为2^16 * 2^ 14   = 2^30 < 2^31。该限制用于防止字节序列号溢出。 
SACK选择确认选项 
1.前言 
TCP通信时,如果发送序列中间某个数据包丢失,TCP会通过重传最后确认的包开始的后续包,这样原先已经正确传输的包也可能重复发送,急剧降低了TCP性能。为改善这种情况,发展出SACK(Selective Acknowledgment, 选择性确认)技术,使TCP只重新发送丢失的包,不用发送后续所有的包,而且提供相应机制使接收方能告诉发送方哪些数据丢失,哪些数据重发了,哪些数 据已经提前收到等。 
2.选项格式 
SACK信息是通过TCP头的选项部分提供的,信息分两种,一种标识是否支持SACK,是在TCP握手时发送;另一种是具体的SACK信息。 
SACK允许选项 
       +---------+--------------+ 
       | Kind=4   | Length=2     | 
       +---------+-------------+ 
该选项只允许在有SYN标志的TCP包中,也即TCP握手的前两个包中,分别表示各自是否支持SACK。 
SACK选项 




选项长度: 可变,但整个TCP选项长度不超过40字节,实际最多不超过4组边界值。
                         +--------+--------+
                         | Kind=5 | Length | 
       +--------+--------+--------+-----------------+ 
       |       Left Edge of 1st Block                 | 
       +--------+--------+--------+-----------------+ 
       |       Right Edge of 1st Block               | 
       +--------+--------+--------+-----------------+ 
       |                                             | 
       /       。。。       . . .   。。。。。         / 
       |                                             | 
       +--------+--------+--------+-----------------+ 
       |       Left Edge of nth Block                 | 
       +--------+--------+--------+----------------+ 
       |       Right Edge of nth Block               | 
       +--------+--------+--------+----------------+ 
该选项参数告诉对方已经接收到并缓存的不连续的数据块,注意都是已经接收的,发送方可根据此信息检查究竟是哪个块丢失,从而发送相应的数据块。 
* Left Edge of Block 
不连续块的第一个数据的序列号。 
* Right Edge of Block 
不连续块的最后一个数据的序列号之后的序列号。表示(Left Edge - 1)和(Right Edge)处序列号的数据没能接收到。 
3.工作过程 
SACK的产生 
SACK通常都是由TCP接收方产生的,在TCP握手时如果接收到对方的SACK允许选项同时自己也支持SACK的话,在接收异常时就可以发送SACK包通知发送方。 


对中间有丢包或延迟时的SACK 
如果TCP接收方接收到非期待序列号的数据块时,如果该块的序列号小于期待的序列号,说明是网络复制或重发的包,可以丢弃;如果收到的数据块序列号大于期待的序列号,说明中间包被丢弃或延迟,此时可以发送SACK通知发送方出现了网络丢包。 
为反映接收方的接收缓存和网络传输情况,SACK中的第一个块必须描述是那个数据块激发此SACK选项的,接收方应该尽可能地在SACK选项部分中填写尽可能多的块信息,即使空间有限不能全部写完,SACK选项中要报告最近接收的不连续数据块,让发送方能了解当前网络传输情况的最新信息。 


对重发包的SACK(D-SACK) 
RFC2883中对SACK进行了扩展,在SACK中描述的是收到的数据段,这些数据段可以是正常的,也可能是重复发送的,SACK字段具有描述重复发送的数据段的能力,在第一块SACK数据中描述重复接收的不连续数据块的序列号参数,其他SACK数据则描述其他正常接收到的不连续数据,因此第一块SACK描述的序列号会比后面的SACK描述的序列号大;而在接收到不完整的数据段的情况下,SACK范围甚至可能小于当前的ACK值。通过这种方法,发送方可以更仔细判断出当前网络的传输情况,可以发现数据段被网络复制、错误重传、ACK丢失引起的重传、重传超时等异常的网络状况。 


发送方对SACK的响应 
TCP发送方都应该维护一个未确认的重发送数据队列,数据未被确认前是不能释放的,这个从重发送队列中的每个数据块都有一个标志位“SACKed”标识是否该块被SACK过,对于已经被SACK过的块,在重新发送数据时将被跳过。发送方接收到接收方SACK信息后,根据SACK中数据标志重发送队列中相应的数据块的“SACKed”标志,但如果接收不到接收方数据,超时后,所有重发送队列中数据块的SACKed位都要清除,因为可能接收方已经出现了异常。 
4.应用举例 
发送方发送的数据   接收方接收的数据(包括SACK)   接收方发送的ACK 


SACK累加接收的数据 
         5000-5499       (该包丢失)
         5500-5999       5500-5999     5000, SACK=5500-6000 
         6000-6499       6000-6499     5000, SACK=5500-6500 
         6500-6999       6500-6999     5000, SACK=5500-7000 
         7000-7499       7000-7499     5000, SACK=5500-7500 
数据包丢失,ACK丢失 
         3000-3499       3000-3499     3500 (ACK包丢失)
         3500-3999       3500-3999     4000 (ACK包丢失) 
         4000-4499       (该包丢失) 
         4500-4999       4500-4999     4000, SACK=4500-5000 (ACK包丢失) 
         3000-3499       3000-3499     4000, SACK=3000-3500, 4500-5000 
                                               ---------此为D-SACK 
数据段丢失和延迟 
         500-999         500-999       1000
         1000-1499       (延迟) 
         1500-1999       (该包丢失) 
         2000-2499       2000-2499     1000, SACK=2000-2500 
         1000-2000       1000-1499     1500, SACK=2000-2500 
         1000-2000     2500, SACK=1000-1500 
                                               ---------此为D-SACK 
数据段丢失且延迟 
         500-999         500-999       1000
         1000-1499       (延迟) 
         1500-1999       (该包丢失) 
         2000-2499       (延迟) 
         2500-2999       (该包丢失) 
         3000-3499       3000-3499     1000, SACK=3000-3500 
         1000-2499       1000-1499     1500, SACK=3000-3500 
         2000-2499     1500, SACK=2000-2500, 3000-3500 
         1000-2499     2500, SACK=1000-1500, 3000-3500 
                                             ---------此为部分D-SACK 
MSS: Maxitum Segment Size 最大分段大小 
1.前言
最大报文段长度(M S S)表示T C P传往另一端的最大块数据的长度。当建立一个连接时,每一方都有用于通告它期望接收的 M S S选项(M S S选项只能出现在S Y N报文段中)。通过MSS,应用数据被分割成TCP认为最适合发送的数据块,由TCP传递给IP的信息单位称为报文段或段(segment)。 
     我们不难联想到,跟最大报文段长度最为相关的一个参数是网络设备接口的MTU,以太网的MTU是1500,基本IP首部长度为20,TCP首部是20,所以MSS的值可达1460(MSS不包括协议首部,只包含应用数据)。 
2.选项格式   
                 +---------+-----------+-------------+--------+ 
                 | Kind=2 |Length=4     |     Mss值             | 
                 +---------+-----------+-------------+--------+ 


3.工作过程 
     从上面我们可以看到,MSS是可以通过SYN段进行协商的(MSS选项只能出现在SYN报文段中),但它并不是任何条件下都可以协商的,如果一方不接受来自另一方的MSS值(不带MMS选项即代表不接受),则MSS就定为默认值536字节。 
     这里有必要介绍路径M T U的概念。路径M T U当前在两个主机之间的路径上任何网络上的最小M T U。路径M T U的发现可以通过在I P首部中设置“不要分片( D F)”比特,来发现当前路径上的路由器是否需要对正在发送的 I P数据报进行分片。如果一个待转发的 I P数据报被设置D F比特,而其长度又超过了 M T U,那么路由器将返回 I C M P不可达的差错。 
TCP的路径MTU发现按如下方式进行: 
①在连接建立时,TCP使用输出接口或对端声明的MSS中的最小MTU作为起始的报文段大小。路径 MTU发现不允许TCP超过对端声明的MSS。如果对端没有指定一个MSS,则默认为536。 
②一旦选定了起始的报文段大小,在该连接上的所有被 T C P发送的I P数据报都将被设置DF比特。如果某个中间路由器需要对一个设置了 D F标志的数据报进行分片,它就丢弃这个数据报,并产生一个ICMP的“不能分片”差错。 
③如果收到这个ICMP差错,TCP就减少段大小并进行重传。如果路由器产生的是一个较新的该类ICMP差错,则报文段大小被设置为下一跳的 MTU减去IP和TCP的首部长度。如果是一个较旧的该类ICMP差错,则必须尝试下一个可能的最小 MTU。当由这个ICMP差错引起的重传发生时,拥塞窗口不需要变化,但要启动慢启动。 
④由于路由可以动态变化,因此在最后一次减少路径 M T U的一段时间以后,可以尝试使用一个较大的值。 
Timestamp时间戳选项
1.前言 
     时间戳选项使发送方在每个报文段中放置一个时间戳值。接收方在确认中返回这个数值,从而允许发送方为每一个收到的 A C K计算RT T(我们必须说“每一个收到的 A C K”而不是“每一个报文段”,是因为T C P通常用一个A C K来确认多个报文段)。我们提到过目前许多实现为每一个窗口只计算一个 RT T,对于包含8个报文段的窗口而言这是正确的。然而,较大的窗口大小则需要进行更好的RT T计算。 
2.选项格式    
+---+-------+--------+-------+-------+-------+--------+------+--------+ 
| Kind=8 | Length=10 |         时间戳           | 时间戳回显应答         | 
+-----------------------------------+---------------------------------+ 
3.工作过程 
     时间戳是一个单调递增的值。由于接收方只需要回显收到的内容,因此不需要关注时间戳单元是什么。这个选项不需要在两个主机之间进行任何形式的时钟同步。 RFC 1323推荐在1毫秒和1秒之间将时间戳的值加1。 
     在连接建立阶段,对这个选项的规定与前一节讲的窗口扩大选项类似。主动发起连接的一方在它的S Y N中指定选项。只有在它从另一方的 S Y N中收到了这个选项之后,该选项才会在以后的报文段中进行设置。 
     我们已经看到接收方 T C P不需要对每个包含数据的报文段进行确认,许多实现每两个报 
文段发送一个A C K。如果接收方发送一个确认了两个报文段的 A C K,那么哪一个收到的时间 戳应当放入回显应答字段中来发回去呢? 
     为了减少任一端所维持的状态数量,对于每个连接只保持一个时间戳的数值。选择何时更新这个数值的算法非常简单: 
1) TCP跟踪下一个A C K中将要发送的时间戳的值(一个名为 t s re c e n t的变量)以及最后发送的A C K中的确认序号(一个名为l a s t a c k的变量)。这个序号就是接收方期望的序号。 
2)   当一个包含有字节号l a s t a c k的报文段到达时,则该报文段中的时间戳被保存在 t s re c e n t中。 
3)   无论何时发送一个时间戳选项, t s re c e n t就作为时间戳回显应答字段被发送,而序号字段被保存在l a s t a c k中。 




Linux下相关的TCP参数配置 
1. /proc/sys/net/core/rmem_max — 最大的TCP数据接收缓冲 
2. /proc/sys/net/core/wmem_max — 最大的TCP数据发送缓冲 
3. /proc/sys/net/ipv4/tcp_timestamps — 时间戳在(请参考RFC 1323)TCP的包头增加12个字节 
4. /proc/sys/net/ipv4/tcp_sack — 有选择的应答 
5. /proc/sys/net/ipv4/tcp_window_scaling — 支持更大的TCP窗口. 
6. /proc/sys/net/core/rmem_default — 默认的接收窗口大小 
7. /proc/sys/net/core/rmem_max — 接收窗口的最大大小 
8. /proc/sys/net/core/wmem_default — 默认的发送窗口大小 

9. /proc/sys/net/core/wmem_max — 发送窗口的最大大小


转自:http://hi.baidu.com/clusterlee/blog/item/34870719dc53620e34fa4142.html

原创粉丝点击