加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

TCP 的那些事儿之一:TCP协议、算法和原理

发布时间:2019-03-20 04:47:24 所属栏目:教程 来源:cpp软件架构狮
导读:TCP是一个巨伟大的协议,由于他要办理许多题目,而这些题目又带出了许多子题目和幽暗面。以是进修TCP自己是个较量疾苦的进程,但对付进修的进程却能让人有许多收成。关于TCP这个协议的细节,我照旧保举你去看W.Richard Stevens的《TCP/IP 详解 卷1:协议》

可是,这种方法会有较量严峻的题目,那就是由于要死等3,以是会导致4和5即便已经收到了,而发送方也完全不知道产生了什么事,由于没有收到Ack,以是,发送方也许会气馁地以为也丢了,以是有也许也会导致4和5的重传。

对此有两种选择:

  • 一种是仅重传timeout的包。也就是第3份数据。
  • 另一种是重传timeout后全部的数据,也就是第3,4,5这三份数据。

这两种方法有好也有欠好。第一种会节减带宽,可是慢,第二种会快一点,可是会挥霍带宽,也也许会有无勤奋。但总体来说都欠好。由于都在等timeout,timeout也许会很长(在下篇会说TCP是怎么动态地计较出timeout的)。

快速重传机制

于是,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。表示图如下:

Fast Retransmit只办理了一个题目,就是timeout的题目,它依然面对一个艰巨的选择,就是,是重传之前的一个照旧重传全部的题目。对付上面的示例来说,是重传#2呢照旧重传#2,#3,#4,#5呢?由于发送端并不清晰这持续的3个ack(2)是谁传返来的?大概发送端发了20份数据,是#6,#10,#20传来的呢。这样,发送端很有也许要重传从2到20的这堆数据(这就是某些TCP的现实的实现)。可见,这是一把双刃剑。

SACK 要领

其它一种更好的方法叫:Selective Acknowledgment (SACK)(参看RFC 2018),这种方法必要在TCP头里加一个SACK的对象,ACK照旧Fast Retransmit的ACK,SACK则是讲述收到的数据碎版。参看下图:

这样,在发送端就可以按照回传的SACK来知道哪些数据到了,哪些没有到。于是就优化了Fast Retransmit的算法。虽然,这个协议必要双方都支持。在 Linux下,可以通过tcp_sack参数打开这个成果(Linux 2.4后默认打开)。

这里还必要留意一个题目——吸取方Reneging,所谓Reneging的意思就是吸取方有权把已经报给发送端SACK里的数据给丢了。这样干是不被勉励的,由于这个事会把题目伟大化了,可是,吸取方这么做也许会有些极度环境,好比要把内存给此外更重要的对象。以是,发送方也不能完全依靠SACK,照旧要依靠ACK,并维护Time-Out,假如后续的ACK没有增添,,那么照旧要把SACK的对象重传,其它,吸取端这边永久不能把SACK的包标志为Ack。

留意:SACK会斲丧发送方的资源,试想,假如一个进攻者给数据发送方发一堆SACK的选项,这会导致发送方开始要重传乃至遍历已经发出的数据,这会耗损许多发送端的资源。具体的对象请参看《TCP SACK的机能衡量》。

Duplicate SACK – 一再收到数据的题目

Duplicate SACK又称D-SACK,其首要行使了SACK来汇报发送方有哪些数据被一再吸取了。RFC-2883 里有具体描写和示例。下面举几个例子(来历于RFC-2883)

D-SACK行使了SACK的第一个段来做符号,

  • 假如SACK的第一个段的范畴被ACK所包围,那么就是D-SACK
  • 假如SACK的第一个段的范畴被SACK的第二个段包围,那么就是D-SACK

示例一:ACK丢包

下面的示例中,丢了两个ACK,以是,发送端重传了第一个数据包(3000-3499),于是吸取端发明一再收到,于是回了一个SACK=3000-3500,由于ACK都到了4000意味着收到了4000之前的全部数据,以是这个SACK就是D-SACK——旨在汇报发送端我收到了一再的数据,并且我们的发送端还知道,数据包没有丢,丢的是ACK包。

  • Transmitted Received ACK Sent
  • Segment Segment (Including SACK Blocks)
  • 3000-3499 3000-3499 3500 (ACK dropped)
  • 3500-3999 3500-3999 4000 (ACK dropped)
  • 3000-3499 3000-3499 4000, SACK=3000-3500
  • ---------

示例二,收集拖延

下面的示例中,收集包(1000-1499)被收集给拖延了,导致发送方没有收到ACK,尔后头达到的三个包触发了“Fast Retransmit算法”,以是重传,但重传时,被拖延的包又到了,以是,回了一个SACK=1000-1500,由于ACK已到了3000,以是,这个SACK是D-SACK——标识收到了一再的包。

这个案例下,发送端知道之前由于“Fast Retransmit算法”触发的重传不是由于发出去的包丢了,也不是由于回应的ACK包丢了,而是由于收集延时了。

  • Transmitted Received ACK Sent
  • Segment Segment (Including SACK Blocks)
  • 500-999 500-999 1000
  • 1000-1499 (delayed)
  • 1500-1999 1500-1999 1000, SACK=1500-2000
  • 2000-2499 2000-2499 1000, SACK=1500-2500
  • 2500-2999 2500-2999 1000, SACK=1500-3000
  • 1000-1499 1000-1499 3000
  • 1000-1499 3000, SACK=1000-1500
  • ---------

可见,引入了D-SACK,有这么几个甜头:

1)可以让发送方知道,是发出去的包丢了,照旧返来的ACK包丢了。

2)是不是本身的timeout太小了,导致重传。

3)收集上呈现了先发的包后到的环境(又称reordering)

4)收集上是不是把我的数据包给复制了。

知道这些对象可以很好得辅佐TCP相识收集环境,从而可以更好的做收集上的流控。

Linux下的tcp_dsack参数用于开启这个成果(Linux 2.4后默认打开)。

【责任编辑:武晓燕 TEL:(010)68476606】
点赞 0

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读