8tcp为什么是可靠的,tcp如何保证顺序【重点】【yetdone】

https://mp.weixin.qq.com/s/7WZ0_lOrxiVrz-3OTPkLaA

 

0 连接握手 3次4次

[专项]tcp状态机,为什么3次握手(很好)(done)

 

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。示意图如下:

[通俗易懂]深入理解TCP协议(上):理论基础_7.png

 

 

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给应用层(用户空间)

 

 后一个包的Seq号等于前一个包的Seq Len(三次握手和四次挥手是例外,SYN和FIN无len,但是会占用一个seq)。https://www.cnblogs.com/ct20150811/p/9431992.html 内有对缺包和乱序的丰富图例
 
5 流量控制
 
 
 
6 滑动窗口协议
 
6.1 为什么要有滑动窗口协议:https://www.cnblogs.com/vamei/archive/2012/12/08/2805252.html
上面的工作方式中,发送方保持发送->等待ACK->发送->等待ACK...的单线工作方式,这样的工作方式叫做stop-and-wait。stop-and-wait虽然实现了TCP通信的可靠性,但同时牺牲了网络通信的效率。在等待ACK的时间段内,我们的网络都处于闲置(idle)状态。我们希望有一种方式,可以同时发送出多个片段。
 
6.2 nagle算法和滑动窗口协议是否冲突?https://www.zhihu.com/question/268814201/answer/342135750?from=singlemessage&isappinstalled=0&s_r=0&utm_medium=social&utm_oi=1003056052560101376&utm_source=wechat_session
nagle只允许一个没有被确认的分组,在没收到对方确认前不会发送已经缓存的数据,那么,当前滑动窗口还有意义吗,并且后面说的那个快重传和和快恢复,是对方收到一个失序报文,那么nagle怎么会出现那种情况。
大部分情况可以填满mss
 
6.3 怎么做 https://blog.csdn.net/u013898698/article/details/61615356
1)根据连接之初接收端的len,发送端构造发送滑动窗口
2)当A成功发送了数据,即发送的数据得到了B的确认(ack)之后,才会移动滑动窗口离开已发送的数据(将ack以下seq包释放);同时B则确认连续的数据分组,对于乱序的分组则先接收下来,避免网络重复传递:
 
 
 
7 拥塞控制 http://www.52im.net/thread-515-1-1.html
具体一点,我们知道TCP通过一个timer采样了RTT并计算RTO,但是,如果网络上的延时突然增加,那么,TCP对这个事做出的应对只有重传数据,但是,重传会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,于是,这个情况就会进入恶性循环被不断地放大。试想一下,如果一个网络内有成千上万的TCP连接都这么行事,那么马上就会形成“网络风暴”,TCP这个协议就会拖垮整个网络。这是一个灾难。

所以,TCP不能忽略网络上发生的事情,而无脑地一个劲地重发数据,对网络造成更大的伤害。对此TCP的设计理念是:TCP不是一个自私的协议,当拥塞发生的时候,要做自我牺牲。就像交通阻塞一样,每个车都应该把路让出来,而不要再去抢路了

拥塞控制主要是四个算法:

  • 1)慢启动;
  • 2)拥塞避免;
  • 3)拥塞发生;
  • 快重传
  • 4)快速恢复。

慢启动的意思是,刚刚加入网络的连接,一点一点地提速,不要一上来就像那些特权车一样霸道地把路占满。新同学上高速还是要慢一点,不要把已经在高速上的秩序给搞乱了。
 
https://www.cnblogs.com/fly-bryant/p/13353562.html
快重传机制当接收方收到一个序号大于下一个所期望(最后一个发出的ack)的报文段时,就检测到了数据流中的一个间格,于是发送三个冗余的 ACK,客户端收到后,就在定时器过期之前,重传丢失的报文段。
 
 
8 数据分片

 

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,而我们的发送方会义无反顾地发送这几个字节。

 

 

 

 

 

posted on 2019-11-25 14:03  silyvin  阅读(869)  评论(0编辑  收藏  举报