TCP Retransmission的理解

TCP  Retransmission:TCP重传,因为网络数据包未被ACK确认,为避免数据丢失而进行错误恢复,出现重传的原因很多:

服务器性能下降、网络数据拥塞、网络不稳定抖动、程序bug、网络设备故障等都有可能导致数据重传。

下面模拟下TCP重传的现象:

写一个测试用的服务器和客户端Socket连接:

客户端发送代码如下:

for (int i = 0; i < 5; i++)
                {
                    client.SendAsync(string.Format("!#{0}$!", (i + 1).ToString() + ":>Hello"));
                    Thread.Sleep(200);
                }

 服务器端为一个带起始和结束符的格式解析。开启Wireshark抓包,包过滤的条件参考如下:

((ip.dst==192.168.11.151 and ip.src==192.168.11.140) or (ip.dst==192.168.11.140 and ip.src==192.168.11.151)) and tcp and tcp.port==8500

当点击发送后,拔掉网线等待1到2秒后插回;观察抓取到的数据包:

可以看到15:04:13时,出现了一次TCP Retransmission: !#3:>Hello$!!#4:>Hello$!!#5:>Hello$!

接着:TCP Acked unseen segment: unseen是未找到,意思是数据包ACK的消息未被Wireshark抓取到。但未被抓取到并不代表数据未被发送:

查看服务器端接收区:说明数据被正确的重传接收了。

 

下文为重传的机制介绍:引用网络:原文出处:http://www.myexception.cn/h/545728.html

引:

TCP Retransmission的机制:当发送方送出一个TCP片段后,将开始计时,等待该TCP片段的ACK回复。如果接收方正确接收到符合次序的片段,接收方会利用ACK片段回复发送方。发送方得到ACK回复后,继续移动窗口,发送接下来的TCP片段。如果直到计时完成,发送方还是没有收到ACK回复,那么发送方推断之前发送的TCP片段丢失,因此重新发送之前的TCP片段。这个计时等待的时间叫做重新发送超时时间(RTO, retransmission timeout)。

发送方应该在等待多长时间之后重新发送呢?这是重新发送的核心问题。上述过程实际上有往返两个方向:1. 发送片段从发送方到接收方的传输,2. ACK片段从接收方到发送方的传输。整个过程实际耗费的时间称做往返时间(RTT, round trip time)。如果RTT是固定的,比如1秒,那么我们可以让RTO等于RTT。但实际上,RTT的上下浮动很大。比如某个时刻,网络中有许多交通,那么RTT就增加。在RTT浮动的情况下,如果我们设置了过小的RTO,那么TCP会等待很短的时间之后重新发送,而实际上之前发送的片段并没有丢失,只是传输速度比较慢而已,这样,网络中就被重复注入TCP片段,从而浪费网络传输资源。另一方面,如果RTO时间过长,那么当TCP片段已经实际丢失的情况下,发送方不能及时重新发送,会造成网络资源的闲置。所以,RTO必须符合当前网络的使用状况。网络状况越好,RTO应该越短;网络状况越差,RTO应该越长。

TCP协议通过统计RTT,来决定合理的RTO。发送方可以测量每一次TCP传输的RTT (从发送出数据片段开始,到接收到ACK片段为止),这样的每次测量得到的往返时间,叫做采样RTT(srtt, sampling round trip time)。建立连接之后,每次的srtt作为采样样本,计算平均值(mean)和标准差(standard deviation),并让RTO等于srtt平均值加上四倍的srtt标准差。

RTO = mean + 4 std

(上述算法有多个变种,根据平台不同有所变化)

平均值反映了平均意义上的RTT,平均往返时间越大,RTO越大。另一方面,标准差越大也会影响RTO。标准差代表了RTT样本的离散程度。如果RTT上下剧烈浮动,标准差比较大。RTT浮动大,说明当前网络状况相对不稳定。因此要设置更长的RTO,以应对不稳定的网络状况。

你可能感兴趣的:(Socket)