TCP重传机制
这里的文章重传已经写的比较好的一篇,因此,直接拿来参考!
TCP要保证所有的数据包都可以到达,所以,必需要有重传机制。
超时重传机制:就是发送端死等接收端的ack,直到发送端超时之后,在发送一个包,直到收到接收端的ack为止。
例如:接收端给发送端的Ack确认只会确认最后一个连续的包,比如,发送端发了1,2,3,4,5一共五份数据,接收端收到了1,2,于是回ack 3,然后收到了4(注意此时3没收到),此时的TCP会怎么办?等待发送端的ACK 3,直到超时后,就会再发送3.面临一个艰难的选择,就是,是重传之前的一个还是重传所有的问题。对于上面的示例来说,是重传#3呢还是重传#3,#4,#5呢?
快速重传机制:这个机制不以时间为驱动,而是以数据来重传!如果接收端包收包没有连续到达,就ACK最后那个可能被丢了的包,如果发送方连续收到接收端3次相同的ack,就重传。
这样,在发送端就可以根据回传的SACK来知道哪些数据到了,哪些没有到。于是就优化了Fast Retransmit的算法。当然,这个协议需要两边都支持。在 Linux下,可以通过tcp_sack参数打开这个功能(Linux 2.4后默认打开)。
这里还需要注意一个问题——接收方Reneging,所谓Reneging的意思就是接收方有权把已经报给发送端SACK里的数据给丢了。这样干是不被鼓励的,因为这个事会把问题复杂化了,但是,接收方这么做可能会有些极端情况,比如要把内存给别的更重要的东西。所以,发送方也不能完全依赖SACK,还是要依赖ACK,并维护Time-Out,如果后续的ACK没有增长,那么还是要把SACK的东西重传,另外,接收端这边永远不能把SACK的包标记为Ack。
注意:SACK会消费发送方的资源,试想,如果一个攻击者给数据发送方发一堆SACK的选项,这会导致发送方开始要重传甚至遍历已经发出的数据,这会消耗很多发送端的资源。详细的东西请参看《TCP SACK的性能权衡》
Duplicate SACK – 重复收到数据的问题
Duplicate SACK又称D-SACK,其主要使用了SACK来告诉发送方有哪些数据被重复接收了。RFC-2883 里有详细描述和示例。下面举几个例子(来源于RFC-2883)
D-SACK使用了SACK的第一个段来做标志,
- 如果SACK的第一个段的范围被ACK所覆盖,那么就是D-SACK
- 如果SACK的第一个段的范围被SACK的第二个段覆盖,那么就是D-SACK
示例一:ACK丢包
下面的示例中,丢了两个ACK,所以,发送端重传了第一个数据包(3000-3499),于是接收端发现重复收到,于是回了一个SACK=3000-3500,因为ACK都到了4000意味着收到了4000之前的所有数据,所以这个SACK就是D-SACK——旨在告诉发送端我收到了重复的数据,而且我们的发送端还知道,数据包没有丢,丢的是ACK包。
1
2
3
4
5
6
7
|
Transmitted Received ACK Sent Segment Segment (Including SACK Blocks) 3000-3499 3000-3499 3500 (ACK dropped) 3500-3999 3500-3999 4000 (ACK dropped) 3000-3499 3000-3499 4000, SACK=3000-3500 ---------
|
示例二,网络延误
下面的示例中,网络包(1000-1499)被网络给延误了,导致发送方没有收到ACK,而后面到达的三个包触发了“Fast Retransmit算法”,所以重传,但重传时,被延误的包又到了,所以,回了一个SACK=1000-1500,因为ACK已到了3000,所以,这个SACK是D-SACK——标识收到了重复的包。
这个案例下,发送端知道之前因为“Fast Retransmit算法”触发的重传不是因为发出去的包丢了,也不是因为回应的ACK包丢了,而是因为网络延时了。
1
2
3
4
5
6
7
8
9
10
11
|
Transmitted Received ACK Sent Segment Segment (Including SACK Blocks) 500-999 500-999 1000 1000-1499 (delayed) 1500-1999 1500-1999 1000, SACK=1500-2000 2000-2499 2000-2499 1000, SACK=1500-2500 2500-2999 2500-2999 1000, SACK=1500-3000 1000-1499 1000-1499 3000 1000-1499 3000, SACK=1000-1500
---------
|
可见,引入了D-SACK,有这么几个好处:
1)可以让发送方知道,是发出去的包丢了,还是回来的ACK包丢了。
2)是不是自己的timeout太小了,导致重传。
3)网络上出现了先发的包后到的情况(又称reordering)
4)网络上是不是把我的数据包给复制了。
知道这些东西可以很好得帮助TCP了解网络情况,从而可以更好的做网络上的流控。
Linux下的tcp_dsack参数用于开启这个功能(Linux 2.4后默认打开)
最后,由于最近学习netstat命令,下面就通过一个服务器的命令结果,看下问题:TcpExt:
79 invalid SYN cookies received
8 resets received for embryonic SYN_RECV sockets
9 packets pruned from receive queue because of socket buffer overrun
5 ICMP packets dropped because they were out-of-window
132513 TCP sockets finished time wait in fast timer
5520362 delayed acks sent
4854 delayed acks further delayed because of locked socket
Quick ack mode was activated 265388 times
112119042 packets directly queued to recvmsg prequeue.
255626524 bytes directly in process context from backlog
2657617950 bytes directly received in process context from prequeue
141 packets dropped from prequeue
2779493398 packet headers predicted
108242651 packets header predicted and directly queued to user
209035695 acknowledgments not containing data payload received
1531587862 predicted acknowledgments
131551 times recovered from packet loss by selective acknowledgements
279 bad SACK blocks received
Detected reordering 10 times using FACK
Detected reordering 19 times using SACK
Detected reordering 37 times using time stamp
214 congestion windows fully recovered without slow start
20 congestion windows partially recovered using Hoe heuristic
3246 congestion windows recovered without slow start by DSACK
61602 congestion windows recovered without slow start after partial ack
TCPLostRetransmit: 31880
12361 timeouts after SACK recovery
289 timeouts in loss state
498564 fast retransmits
13967 forward retransmits
42221 retransmits in slow start
56690 other TCP timeouts
TCPLossProbes: 1113019
TCPLossProbeRecovery: 928744
7366 SACK retransmits failed
13 times receiver scheduled too late for direct processing
967 packets collapsed in receive queue due to low socket buffer
267981 DSACKs sent for old packets
520 DSACKs sent for out of order packets
966679 DSACKs received
1611 DSACKs for out of order packets received
265 connections reset due to unexpected data
105 connections reset due to early user close
1132 connections aborted due to timeout
TCPDSACKIgnoredOld: 4605
TCPDSACKIgnoredNoUndo: 723291
TCPSpuriousRTOs: 13632
TCPSackShifted: 701131
TCPSackMerged: 540339
TCPSackShiftFallback: 1468281
TCPBacklogDrop: 7
TCPRetransFail: 126
TCPRcvCoalesce: 74902345
TCPOFOQueue: 61476920
TCPOFOMerge: 521
TCPChallengeACK: 1636
TCPSYNChallenge: 1600
TCPSpuriousRtxHostQueues: 159
Detected reordering 10 times using FACK
Detected reordering 19 times using SACK
Detected reordering 37 times using time stamp
267981 DSACKs sent for old packets
520 DSACKs sent for out of order packets
966679 DSACKs received
1611 DSACKs for out of order packets received
上一篇: 搭建dhcp服务器