TCP Retransmission
TCP Retransmission 造成的原因有哪些? - 知乎 https://www.zhihu.com/question/586578058/answer/2916704280
在Wireshark抓包分析中,“TCP Retransmission”(TCP 重传)和"TCP Dup ACK"(TCP 重复确认)是两种不同的现象,表示了TCP通信中可能出现的问题。下面是它们的区别:
-
TCP Retransmission(TCP 重传):
当发送方的TCP在一定时间内没有收到确认(ACK)的响应时,它会认为数据包丢失了或者没有成功传输,于是会重新发送相同的数据包。这个过程就称为TCP重传。在Wireshark中,你会看到一个标记为"TCP Retransmission"的事件,它表示同一个序列号的数据包被发送多次,因为之前的那次发送没有得到确认。 -
TCP Dup ACK(TCP 重复确认):
当接收方收到一个失序的数据包时,它会发送一个重复确认(Dup ACK)来告诉发送方它已经收到了一些数据,但是它还在等待之前的失序数据包。这是为了帮助发送方重传丢失的数据包。在Wireshark中,你会看到一个标记为"TCP Dup ACK"的事件,它表示接收方已经收到了重复的确认,这通常暗示着之前的某个数据包丢失了。
总结:
- TCP Retransmission 是发送方为了确保数据的可靠传输而重发丢失的数据包。
- TCP Dup ACK 是接收方为了指示发送方它需要丢失的数据包而发送的重复确认。
wireshark抓包中TCP Retransmission和TCP Dup ACK的区别 http://lihuaxi.xjx100.cn/news/1431073.html?action=onClick
重传的第一个原因是,发往对端的数据包超时了。当A像对端发送一个数据包之后,为了确实对端真的收到了数据包,会期望收到对端的一个确认包。比如,A发送了一个1号包,然后收到了对方对1号包确认的确认包。就证明1号包对端收到了。当A发送一个数据包的时候,就会放一个定时器,假如这个定时器超时了,就表明这个包对端没收到,此时A就需要把这个包重新发送一遍,这就是重传,一个因为超时导致的重传,叫做超时重传。
希望上面的,你能看懂,然后开始复杂了。
为了防止出现拥塞,tcp的设计需要慢慢尝试,比如第一次发一个包,下一次翻倍,等到达某个阈值,就把这个过程放缓比如每次增加一。两个阶段分别是慢启动和拥塞避免。然后tcp就可以使用合适速率发送数据包了。
当出现超时重传的时候,就说明网络有问题了,比如出现了拥塞,说明之前我们尝试出来的值不适合当前情况了。需要重新尝试,然后又开始慢启动,拥塞避免。这时候就有问题了,在这个过程中,tcp并没有使用最高效率在运行。这是不能忍受的。
说另一个超时之前,先说点其他的。
上面我们说了,A向对端发送一个数据包的时候,需要等待对方确认,才能继续发送下一个。没收到确认就得重新发送之前的包。这是最基础的停等协议。
我们能不能发一批,让对面一次确实一批。结论是可以。tcp每个数据包都是有编号的。比如我发送5个数据包,编号为12345,对端收到这五个数据包之后,发现12345五个数据包我都收到了,然后就一个回复一个确认包。这个确认包用来确认5号包。如果我收到了1235四个数据包,那我就只确认3号包。然后,A需要走超时重传从4号包开始发送456789号包。一次确认一批包的过程,叫做延迟确认。
我大学时候学习这一块很是懵逼呀。这些都太模糊了,看不了摸不着。
为了把上面的内容表述清楚,我描述是,真实世界的tcp是怎么样的。
tcp三次握手建立连接,经过慢启动,拥塞避免找到了一个合适的速率。突然,发送出去的5号包,在规定时间内没收到确认。然后开始走超时重传,重新经历慢启动,拥塞避免,达到一个合适的速率。内核计算这个速率发现,这速率很快呀,达到了某个阈值,然后发送一个ping包告诉对端,我觉得可以进去延迟确认了,对端回复了一个pong包,说没问题,我也觉得可以。然后,发送端发送了2345678编号的包,对端回复了一个确认5号的包,说明7号包丢失了。发送端判断可能又拥塞了,然后启动超时重传,慢启动,拥塞避免,再次达到一个合适速率。
超时重传的时间就是这种,只要发生一次,一切回到原点,不管你之前跑的多快。
停下来,我们想想之前的情况,比如A发送了编号为 123456789 9个数据包,比如说5号曹丢了。对端收到了6号包,因为对面没收到5号包,所以只能确认4号包,然后发送了一个确认4号的确认包。其实在收到对端4号包确认包之前,发送端6789都发出去了。所以接收端收到6号包,回复一个4号包的确认,收到一个7号包,回复一个4号包的确认包,收到一个8号包,回复一个4号包的确认包。因为,接收端没收到5号包,永远只能确认目前收到的包。在发送端超时之前,发送端收到了3个4号包确认包。你既然能这么快的响应,那我是不是没有必要退出延迟确认?我只需要把456789重新发一遍就行了呗。这个重传就是快速重传。
以下所有的重传,发生的背景是在延迟确认期间。
在延迟确认过程中,因为前面的包丢失,发送端收到三个连续的确认包就触发快速重传。这时候,不用经历慢启动,只用把速率减半。这样,通信的效率得到了优化,避免了超时重传慢启动的过程。
我专门强调了前面的包。其实定义里面没有这些。加进来是为了方便理解。比如发送123456 6个数据包,如果23中一个包丢失了,接收端要确认456三个包。接受到能收到三个相同的数据包,就可以触发快速重传。如果是4号包丢失,发送端只能收到两个确认包。这时候,没有出发快速重传,等超时计时器到期后就只能触发超时重传,又得经历一遍慢启动了。
有问题就得优化,能不能优化?能!其实,我觉得我网络环境比较稳定,能短时间没收到两个相同的数据包,其实也能说明我的网络时代不拥塞的,我是不是也可以触发快速重传?当然可以,这种两个相同的确认包,就能触发的重传,叫做早期重传。需要开启内核参数。
其实,还有个问题,我发送了1234567这么多包,对端可能就丢了一个3号包,即使是快速重传,也得吧34567都重新发一遍,是不是没必要?那必然没必要呀。接收端可以通过一个叫做SACK的东西,告诉发送端,我就丢了3号包,你把3号包,快速发给我就行!!
还能不能优化?!问,就是能!
发送端发送1234567 7个包,我中间丢失,你能快速重传,你只收到2个确认包,你都敢早期重传,那好了,我现在最后一个包丢了,你怎么办?!能怎么办呀,我也没其他办法了,只能超时重传了。
tcp说,不你还有别的办法,请让内核开启尾丢包探测!当发送7号包时,我除了设置一个超时重传的定时器,我再设置一个短一些的定时器,如果这个定时器超时,我就发一个tlp探测包,问问发送端,7号包到底有没有收到呀。如果对端回复一个7号包的确认包,就说明7号包不是因为拥塞导致的丢包。这样就避免了触发一次超时重传。
其实,抓包你会发现tlp探测包的编号也是7,但是长度没有7号那么长。
其实,上面的那些知识我也不知道,是因为有次抓包发现,丫的,重传包的长度居然和之前的数据包长度不一致?!这你重传有什么鬼用?然后,各种翻越资料,咨询大佬,然后大佬说可能是尾丢包探测。为了确实这种重传包不一致的情况是尾丢包探测触发的重传。我就自己写代码,基于原生socket,复现了三次握手,四次挥手,超时重传,快速重传,早期重传,以及未丢包探测。证明了这就是tlp!