TCP核心机制
前一篇文章 JavaEE: 深入探索TCP网络编程的奇妙世界(一)
书接上文~
TCP核心机制二: 超时重传
在网络传输中,并不会一帆风顺,而是可能出现"丢包情况"~
为啥会丢包?
产生丢包的原因有很多种
- 数据传输的过程中,发生了bit翻转,收到这个数据的接收方/中间的路由器啥的,发现计算校验和对不上了
发现错误,要及时止损,不能将错就错!
于是就把这个数据包丢弃掉了,不再继续往后转发/不交给应用层使用. - 数据传输到某个节点(路由器/交换机),这个节点,负载太高了.
某个路由器,单位时间只能转发N个包,由于现在是网络高峰期,这个路由器单位时间需要转发的包超过N了(发不过来了),那么后续传输过来的数据就可能被这个路由器直接丢弃掉.
TCP如何对抗丢包?
由于丢包这件事情,是完全随机的,是不可预测的.
TCP再怎么厉害,也不可能避免数据发生丢包!
TCP能做的就是,感知到数据是否丢包,如果丢包,就重新再发一次.
假设网络丢包率是10%(数据报到达对方是90%)
10%的丢包是相当高的数字,出现这个情况,都是网络发生严重故障(LOL就卡成ppt了),此时可以赶紧找运营商保修了~我在这里只是举个例子~
此时,进行一次重传,两次传输至少一次到达对方的概率: 1 - 10% * 10% = 99%
传输次数越多,数据到达对方的概率就越大.
关于是否丢包,这个问题需要通过应答报文来区分
- 收到应答报文,说明数据没丢包
- 没收到应答报文,就说明数据丢包了
我们都知道,数据在网络传输过程中是需要消耗时间的.
那么我们来思考一下这个问题: "没有收到应答报文"表明暂时没收到,那么是过一会就收到了,还是永远都收不到??
其实,发送方发送数据之后,会给出一个"时间限制"(超时时间).
如果在这个时间限制之内,没有收到反馈的ack,那么就视为是数据丢包了.
丢包这个过程有两种情况:
- 一是主机A发送数据给B之后,可能因为网络拥堵等原因,导致数据无法达到主机B.
- 二是A发送的数据到达B了,但是A在一个特定的时间间隔内没有收到B发来的确认应答(ACK丢失),于是就会重新发送.
情况一还好说,A重新发一份就是了.
但是情况二就有点麻烦了,因为A又重新发送了一份相同的数据,接收到多份相同数据感觉好像没啥大不了的,但是万一你传输的数据是"扣款"这样的请求呢?
为了解决情况二引发的问题,TCP会对上述情况做处理.
接收方有一个接收缓冲区,收到的数据先进入到缓冲区里,等后续再收到数据,就会根据序号,在缓冲区中,找对应的位置(排序),如果发现,当前序号1-1000这个数据,已经在缓冲区中存在了,那么就会直接把新收到的这个1-1000数据包丢弃掉~
其实就是去重,通过去重来确保应用程序,调用read读出来的数据,是唯一的,不重复的~
超时重传的时间设定
这里的时间,不是固定值,而是动态变化的.
发送方第一次重传,超时时间是 t1 ,如果重传之后,仍然没有ack,还会继续重传,此时的超时时间就变成了 t2.
t2 > t1
每多重传一次,超时时间的间隔就会变大 / 重传的频次会降低.
经过一次重传之后,就能让数据到达对方的概率提高很多,再重传一次,又会提升很多.
反之,如果重传几次,都没有顺利到达,这就说明网络的丢包率已经到达了一个非常高的程度,网络发生了严重故障,大概率没法继续使用了.
此时再重传的快,也没意义,不如省点力气~
当然了,重传也不会无休止的进行,当重传达到一定的次数之后,TCP不会尝试重传,就认为这个连接已经G了.
TCP会先尝试进行"重置/复位 连接",发送一个特殊的数据包"复位报文".
- 如果网络这会恢复了,复位报文就会重新连接,使通信可以继续进行.
- 如果网络还是有严重问题,复位报文也没有得到回应,此时TCP就会单方面放弃连接.
之前讲过,连接就是通信双方各自保存对方的信息.
发送方释放掉信息之前保存的接收方的相关信息,那么这个连接也就没了.
针对上述内容,我们只关注策略,不关注参数.因为参数可以根据需要进行修改,而策略是固定的~
超时时间该如何确定?
- 最理想的状态下,只要找到一个最小的时间,来保证"确认应答一定能在这个时间内返回"就OK.
- 但是这个时间长短,是会随着网络环境的不同,而发生改变.
- 如果超时时间设的太长,那么就会影响整体的重传效率
- 如果超时时间设的太短,那么就有可能会频繁发送重复的包
TCP为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间.
- Linux中(BSD Unix和Windows也是如此),超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍
- 如果重发一次之后,仍然得不到应答,那么将等待2*500ms后进行重传
- 如果仍然得不到应答,那么将等待4*500ms进行重传.以此类推,以指数形式递增.
- 等累积到一定的重传次数,TCP就会认为网络或者对端主机出现异常,就会强制关闭连接.
确认应答,和超时重传,相互补充,共同构建了TCP"可靠传输机制"~
下一篇文章JavaEE: 深入探索TCP网络编程的奇妙世界(三)