文章目录
- 超时重传机制
- 1. 数据重复传输问题
- 2. 如何解决数据重复传输问题
- 3. 重传次数问题
TCP 的工作机制:
确认应答机制
超时重传机制
如果传输数据的时候丢包了该怎么办?
利用 超时重传,也就是超过了一定的时间,如果还没响应就重新传输。
丢包涉及到两种情况:
- 发送的数据丢了。
- 返回的 ACK 丢了。
发送方是区分不了是哪种情况,于是这两种就都会被认为是丢包了。
由于丢包是一个概率性事件,(通常概率较小)因此,如果重新发送一下这个数据报,还是有很大的概率成功传输的。
因此,TCP 就引入了重传机制,在丢包的时候,就要再发一次同样的数据。
如何判断这次传输是丢包了,还是 ACK 还在返回的路上呢?
TCP 直接引入了一个 时间阈值,发送方发送了一个数据之后,就会等待 ACK ,此时就会开始计时。
如果在这个时间阈值之内也没有收到 ACK ,就不管 ACK 是还在路上,还是彻底丢了,就会直接视为丢包了。
就好比老师要收你的作业,你说没带,但是此时老师认为没带就是没写。
1. 数据重复传输问题
这是由于重传,接收方重复的消息收到了两次。
把数据发送过去之后,返回的 ACK 丢包了,由于重传,又把相同的数据重新传输了一遍。
就好比张三妈妈喊他吃饭,他虽然听见了,但是还在忙自己的事情并没有过来。
妈妈就相当于是发送方,张三就相当于是接收方,而张三还没有过来吃饭就相当于是 ACK 还未返回。
这个时候,妈妈就会再喊一遍,张三听到后决定过来吃饭,相当于 ACK 返回了。
张三作为接收方,收到作为发送方的妈妈两次发送的数据。
如果发送的数据是一个支付请求,发生重传后,那将会造成支付两次的情况。
2. 如何解决数据重复传输问题
TCP 对于重复数据的传输是有特殊处理的,也就是去重。
TCP 存在一个 “接受缓冲区” 这样的存储空间(接收方操作系统内核里的一段内存)
每个 TCP 的 socket 对象都有一个接收缓冲区(也有一个发送缓冲区)
主机A 收到 主机B 的数据后,其实是 B 的网卡读到数据了,然后把这个数据放到 B 对应 socket 的 接收缓冲区 中。
后序应用程序使用 getInputStream 进一步的使用 read ,也就是从接收缓冲区里来读数据。
可以把这个 接受缓冲区 想象成一个阻塞队列。
根据数据的序号,TCP 很容易识别当前接收缓冲区里的这两条数据是否是重复的。
如果重复,就把后来的这份数据直接丢弃,保证了应用程序调用 read 读到的数据一定是不重复的。
网络上传输的数据可能会后发先至,TCP 使用这个接收缓冲区,对收到的数据进行重新排序,
使应用程序 read 到的数据是保证有序的(和发送顺序一致)
小结:
由于去重和重新排序机制的存在,发送方只要发现 ACK 还没有按时到达就会重传数据。
即使重复传输了。即使顺序乱了,借助去重和排序,接收方都能很好的处理。(去重和排序都依赖与TCP报头上的序号)
3. 重传次数问题
重传的数据是有可能再次丢包的,因此超时重传是有可能会重传多次的。
但是实际上如果重传了几次后都没有传过去,此时扔继续重传,意义已经不大了。
假设一次传输的丢包概率为 10%(这已经是一个非常大的数字了),那么传输的成功率为 90%。
如果第一次传输丢包,第二次传输也丢包了,此时的的丢包概率是 1%(10% * 10%),如果第三次也丢了,概率就是0.1%。
虽然重传都丢包的概率原则上讲是非常低的,但是如果这个情况真的出现了,只能说明此时丢包的概率远远不止 10%,
或者此时的网络出现了重大事故。
因此,重传达到一定次数的时候就不会继续重传,此时会认为出现了故障。
接下来 TCP 会尝试重置连接(相当于是重连一样),如果重置还是失败,就彻底断开连接。
重传的时候,第一次传重传和第二次重传的超时时间间隔是不一样的,一般来说,重传的轮次越大,超时时间间隔就越大。
超时时间变大,重传的频率就会降低。
因为重传次数越多,说明重传成功的概率就越小,此时重传的太快也是白浪费系统资源。
小结:
可靠传输是 TCP 最核心的部分,TCP 的可靠传输就是通过 确认应答 + 超时重传 来进行体现的。
其中确认应答描述了是传输顺利的情况,而超时重传描述的是传输出现问题的情况。
这两者相会配合,共同支撑整体的 TCP 可靠性。