8tcp为什么是可靠的,tcp如何保证顺序【重点】【yetdone】
https://mp.weixin.qq.com/s/7WZ0_lOrxiVrz-3OTPkLaA
0 连接握手 3次4次
1 tcp确认机制
1.1 什么是tcp确认机制
tcp在数据传输时,发送端先把数据发送到自己的缓存中,然后协议控制将缓存中的数据发往对端,对端返回一个ack=1,发送端则清理缓存中的数据,对端返回ack=0,则重新发送数据,所以tcp是可靠的
而udp发送数据,对端是不会返回确认信息的,因此不可靠
https://www.cnblogs.com/sui776265233/p/9289858.html
1.2 预览tcp如何确认的:https://www.jianshu.com/p/15754b4e9458
sequence number:表示的是我方(发送方)这边,这个packet的数据部分的第一位应该在整个data stream中所在的位置。(注意这里使用的是“应该”。因为对于没有数据的传输,如ACK,虽然它有一个seq,但是这次传输在整个data stream中是不占位置的。所以下一个实际有数据的传输,会依旧从上一次发送ACK的数据包的seq开始) acknowledge number:表示的是期望的对方(接收方)的下一次sequence number是多少。 注意,SYN/FIN的传输虽然没有data,但是会让下一次传输的packet seq增加一,但是,ACK的传输,不会让下一次的传输packet加一。
ack len==0,不占用seq,可见图,所有ack seq都为1
(取自:11读缓冲区(滑动窗口)耗尽与write阻塞、拆包、延迟(一) )
1.3 ack
SeqNum和Ack是以字节数为单位,所以ack的时候,不能跳着确认,只能确认最大的连续收到的包
http://www.52im.net/forum.php?mod=viewthread&tid=513
TCP采用的是累计确认,例如确认号是5,代表5之前序号的包都收到了
第7个报文,ack=1449,表示1449(不含)以前的报文,你发送端就不用管了,我都收到了,你就从1449开始发吧
https://www.cnblogs.com/fly-bryant/p/13353562.html
1.4 超时重传
与mq生产者和消费者防止消息丢失的最佳实践有些相似
RTO根据复杂的公式算出,RTO加倍机制
http://www.52im.net/thread-513-1-1.html 这种方式会导致301 401的重传
TCP引入了一种叫Fast Retransmit 的算法,不以时间驱动,而以数据驱动重传。也就是说,如果,包没有连续到达,就ack最后那个可能被丢了的包,如果发送方连续收到3次相同的ack,就重传。Fast Retransmit的好处是不用等timeout了再重传。
比如:如果发送方发出了1,2,3,4,5份数据,第一份先到送了,于是就ack回2,结果2因为某些原因没收到,3到达了,于是还是ack回2,后面的4和5都到了,但是还是ack回2,因为2还是没有收到,于是发送端收到了三个ack=2的确认,知道了2还没有到,于是就马上重转2。然后,接收端收到了2,此时因为3,4,5都收到了,于是ack回6。示意图如下:
1.5 ttl
1.6 seq回绕
seq为32位无符号
1.7 sack
http://www.52im.net/thread-513-1-1.html
https://www.cnblogs.com/fly-bryant/p/13353562.html
2 /
3 /
4 如何确保顺序
(图片来自:11读缓冲区(滑动窗口)耗尽与write阻塞、拆包、延迟(一))
1)seq,无需经过对方ack来生成,自己就能根据len和上一个seq定出来,ack只是告诉发送端,seq<ack的包我都收到了
发送端根据每个write的报文len,弄好101,201,301,401,进入滑动窗口,顺序发送
2)接收端收到101 一看101的len,计算出当中还有个201,于是ack201,收到301也ack201,401也ack201
发送端重传201,接收端ack501,滑动窗口移动
重组报文顺序从内核copy给应用层(用户空间)
所以,TCP不能忽略网络上发生的事情,而无脑地一个劲地重发数据,对网络造成更大的伤害。对此TCP的设计理念是:TCP不是一个自私的协议,当拥塞发生的时候,要做自我牺牲。就像交通阻塞一样,每个车都应该把路让出来,而不要再去抢路了。
拥塞控制主要是四个算法:
- 1)慢启动;
- 2)拥塞避免;
- 3)拥塞发生;
- 快重传
- 4)快速恢复。
慢启动的意思是,刚刚加入网络的连接,一点一点地提速,不要一上来就像那些特权车一样霸道地把路占满。新同学上高速还是要慢一点,不要把已经在高速上的秩序给搞乱了。
9 持续计时器(Persistence timer) https://blog.csdn.net/TYUTyansheng/article/details/108164681
如果B已经告诉A自己的缓冲区已满,于是A停止发送数据;等待一段时间后,B的缓冲区出现了富余,于是给A发送报文告诉A我的rwnd大小为400,但是这个报文不幸丢失了,于是就出现A等待B的通知||B等待A发送数据的死锁状态。为了处理这种问题,TCP引入了持续计时器(Persistence timer),当A收到对方的零窗口通知时,就启用该计时器,时间到则发送一个1字节的探测报文,对方会在此时回应自身的接收窗口大小,如果结果仍未0,则重设持续计时器,继续等待。
11读缓冲区(滑动窗口)耗尽与write阻塞、拆包、延迟(一)中5s发送端就探测一下
10 糊涂窗口 http://www.52im.net/thread-515-1-1.html
Silly Window Syndrome翻译成中文就是“糊涂窗口综合症”。正如你上面看到的一样,如果我们的接收方太忙了,来不及取走Receive Windows里的数据,那么,就会导致发送方越来越小。到最后,如果接收方腾出几个字节并告诉发送方现在有几个字节的window,而我们的发送方会义无反顾地发送这几个字节。