TCP 协议下 socket 丢包重传机制
参考:
TCP 协议下 socket 有可能丢包吗?
- 在网络层面,传输都可能存在丢包和不可靠。tcp之所以可靠,是因为他有重传机制。但即使如此,也不能说百分之百就一定能送达,也就是当重传还是丢了后,tcp也表示无能为力,几番尝试无果就只能断链接了。当然这时你可以选择重链接,但谁也不能保证重连就一定能连上。所以,一切还是看具体怎么实现,怎么考虑各种极端的网络情况。网络特别特别好,udp传输也不怎么丢包的。
- 同意,TCP可靠是基于双方都知道彼此的字节流的原点,发送方对于自己发送的字节流一定要接收到对方的确认,才会从发送缓冲区彻底删除,如果没有得到确认,会一直重传,如果重传次数到达极限值,则reset TCP 连接。而UDP则不同,把数据发出去就不管了,也没有缓存区来缓存发出去而没有确认的数据,因为压根不会发生,此外也无需内存来保存类似TCP各种状态位。
简单回答的话,在TCP的实现方面,超时重传 快速重传和SACK机制都能在这种情况下实现让客户端重新传输丢掉的第2个包,分别讲讲三种不同的机制
1. 超时重传
客户端通过tcp一次性把数据都发送了出去,在未收到这些发出报文的ack确认之间,这些报文仍然会缓存在发送队列里,如果在限定的时间内(RTO 重传过期时间)没有收到对应报文的ack,那么这些报文需要被重传
RTO不是静态配置的,在这个问题里系统会根据前面三次握手和第一个报文的ack的RTT计算出来一个RTO,这个时间可能是200ms到120s之间的一个值,所有到了RTO时间没有收到ack的报文都需要被重新传送到网络上
2. 快速重传
等待一个RTO的时间太久了,尤其是在RTT比较大的网络环境里,如果丢包率再比较高的情况,那么TCP的效率就会非常低,所以需要通过快速重传机制来实现优化
简单来说,客户端发送的第2个报文丢了,没有收到ack,但服务器在收到第3 4 5个包时会检查他们的顺序编号sequence number,并察觉到与第1个包之间并不连续,于是会发送3个连续的dup ack 给客户端,要求客户端重新发送第1个包后面具有正确sequence number的报文 客户端在收到三个连续的dup ack之后就会确认第2个报文丢掉了,于是实现立即重传而不用再等到RTO的过期时间
3. SACK selective acknowledgment
如果只是丢了第2个包其实快速重传机制就已经可以搞定了,但如果在中间丢了多个报文的时候,比如2-9之间可能丢了第3,第5和第7个报文,其他报文都已经顺利到达服务器,如果只有快速重传,那么客户端需要重传从3到第7个之间的所有报文,而如果客户端和服务器都支持sack的话,服务器端就可以通过sack选项来告知发送方到底丢了哪些报文,这样客户端就只需要把对应丢失的报文重传就好了