CategoryTCP

【转】从TCP到QUIC:从Telnet到HTTP2.0

事情从20世纪70年代开始。

不得不说,人们最初的想法是不要让应用感知网络的存在,分层模型早已有之,网络层协议会处理网络细节。这就使得不管最终谁成了传输协议的标准,都一定要是端到端的。从业务的角度看,人们希望通过网络远程登录一台UNIX主机,这也就使得Telnet成了TCP/IP体系下最为古老的协议之一,一直到今天,我们依然在使用它(虽然现在它已经退化成端口测试工具了)(现在一般用更安全的SSH)。

See also: 【转】End-to-End Principle

我们来看看Telnet这一类程序的特点:

  • 远程输入必须到达主机,一个字节都不能丢;
  • 远程输出必须到达终端显示,一个字节都不能丢;
  • 输入的顺序必须和主机接收的顺序一致,不能乱序;
  • 输出的顺序必须和终端接收的顺序一致,不能乱序。

这写特征可以总结为强时序依赖,你很难跳过一些步骤提前做以后的事情,因为未来的输出依赖于此前的输入。这注定未来承载Telnet的协议需要构建的是一个双向串行流

为了在一个不可靠的网络中构建端到端的可靠的双向串行流,主机需要做什么以及怎么做?

从资源的角度来看,20世纪70年代是一个资源匮乏的年代,无论是带宽还是内存,如果说网络是不可靠的,为了在主机端保证可靠性(*),排队论告诉我们这注定会让主机的内存利用率指数级膨胀,最终系统崩溃。

(*):按照字节顺序排队且不能丢

另一方面,请了解一下停等协议,这应该是最简单的实现上述可靠按序需求的主机端方案(端到端需求)了,嗯,就是它了!

人们很自然地会从停等协议得到扩展,如果能1个字节停等,那就能2个字节停等,那为什么不是n个字节停等?因此,这注定了所谓的TCP协议实现所具有的超级特征,即:

  • n字节停等,n字节积累确认;

【转】ACKnowledgments in TCP

Cumulative ACK

Background: too many ACK segments would waste networking resources which should be used to transfer data from Application Layer.

Cumulative acknowledgment is a process in which the receiver sends a single acknowledgment in response to a finite number …

【转】TCP协议疑难杂症全景解析

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dog250/article/details/6612496

说明:

1).本文以TCP的发展历程解析容易引起混淆,误会的方方面面
2).本文不会贴大量的源码,大多数是以文字形式描述,我相信文字看起来是要比代码更轻松的
3).针对对象:对TCP已经有了全面了解的人。因为本文不会解析TCP头里面的每一个字段或者3次握手的细节,也不会解释慢启动和快速重传的定义
4).除了《TCP/IP详解》(卷一,卷二)以及《Unix网络编程》以及Linux源代码之外,学习网络更好的资源是RFC

5).本文给出一个提纲,如果想了解细节,请直接查阅RFC

6).翻来覆去,终于找到了这篇备忘,本文基于这篇备忘文档修改。

1.网络协议设计

ISO提出了OSI分层网络模型,这种分层模型是理论上的,TCP/IP最终实现了一个分层的协议模型,每一个层次对应一组网络协议完成一组特定的功能,该组网络协议被其下的层次复用和解复用。这就是分层模型的本质,最终所有的逻辑被编码到线缆或者电磁波。
分层模型是很好理解的,然而对于每一层的协议设计却不是那么容易。TCP/IP的漂亮之处在于:协议越往上层越复杂。我们把网络定义为互相连接在一起的设备,网络的本质作用还是“端到端”的通信,然而希望互相通信的设备并不一定要“直接”连接在一起,因此必然需要一些中间的设备负责转发数据,因此就把连接这些中间设备的线缆上跑的协议定义为链路层协议,实际上所谓链路其实就是始发与一个设备,通过一根线,终止于另一个设备。我们把一条链路称为“一跳”。因此一个端到端的网络包含了“很多跳”。

2.TCP和IP协议

终止于IP协议,我们已经可以完成一个端到端的通信,为何还需要TCP协议?这是一个问题,理解了这个问题,我们就能理解TCP协议为何成了现在这个样子,为何如此“复杂”,为何又如此简单。
正如其名字所展示的那样,TCP的作用是传输控制,也就是控制端到端的传输,那为何这种控制不在IP协议中实现的。答案很简单,那就是这会增加IP协议的复杂性,而IP协议需要的就是简单。这是什么原因造成的呢?
首先我们认识一下为何IP协议是沙漏的细腰部分。它的下层是繁多的链路层协议,这些链路提供了相互截然不同且相差很远的语义,为了互联这些异构的网络,我们需要一个网络层协议起码要提供一些适配的功能,另外它必然不能提供太多的“保证性服务”,因为上层的保证性依赖下层的约束性更强的保证性,你永远无法在一个100M吞吐量的链路之上实现的IP协议保证1000M的吞吐量…
IP协议设计为分组转发协议,每一跳都要经过一个中间节点,路由的设计是TCP/IP网络的另一大创举,这样,IP协议就无需方向性,路由信息和协议本身不再强关联,它们仅仅通过IP地址来关联,因此,IP协议更加简单。路由器作为中间节点也不能太复杂,这涉及到成本问题,因此路由器只负责选路以及转发数据包。
因此传输控制协议必然需要在端点实现。在我们详谈TCP协议之前,首先要看一下它不能做什么,由于IP协议不提供保证,TCP也不能提供依赖于IP下层链路的这种保证,比如带宽,比如时延,这些都是链路层决定的,既然IP协议无法修补,TCP也不能,然而它却能修正始于IP层的一些“不可保证性质”,这些性质包括IP层的不可靠,IP层的不按顺序,IP层的无方向/无连接。
将该小节总结一下,TCP/IP模型从下往上,功能增加,需要实现的设备减少,然而设备的复杂性却在增加,这样保证了成本的最小化,至于性能或者因素,靠软件来调节吧,TCP协议就是这样的软件,实际上最开始的时候,TCP并不考虑性能,效率,公平性,正是考虑了这些,TCP协议才复杂了起来。

3.TCP协议

这是一个纯软件协议,为何将其设计上两个端点,参见上一小节,本节详述TCP协议,中间也穿插一些简短的论述。

3.1.TCP协议

确切的说,TCP协议有两重身份,作为网络协议,它弥补了IP协议尽力而为服务的不足,实现了有连接,可靠传输,报文按序到达。作为一个主机软件,它和UDP以及左右的传输层协议隔离了主机服务和网络,它们可以被看做是一个多路复用/解复用器,将诸多的主机进程数据复用/解复用到IP层。可以看出,不管从哪个角度,TCP都作为一个接口存在,作为网络协议,它和对端的TCP接口,实现TCP的控制逻辑,作为多路复用/解复用器,它和下层IP协议接口,实现协议栈的功能,而这正是分层网络协议模型的基本定义(两类接口,一类和下层接口,另一类和对等层接口)。
我们习惯于将TCP作为协议栈的最顶端,而不把应用层协议当成协议栈的一部分,这部分是因为应用层被TCP/UDP解复用了之后,呈现出了一种太复杂的局面,应用层协议用一种不同截然不同的方式被解释,应用层协议习惯于用类似ASN.1标准来封装,这正体现了TCP协议作为多路复用/解复用器的重要性,由于直接和应用接口,它可以很容易直接被应用控制,实现不同的传输控制策略,这也是TCP被设计到离应用不太远的地方的原因之一。
总之,TCP要点有四,一曰有连接,二曰可靠传输,三曰数据按照到达,四曰端到端流量控制。注意,TCP被设计时只保证这四点,此时它虽然也有些问题,然而很简单,然而更大的问题很快呈现出来,使之不得不考虑和IP网络相关的东西,比如公平性,效率,因此增加了拥塞控制,这样TCP就成了现在这个样子。

3.2.有连接,可靠传输,数据按序到达的TCP

IP协议是没有方向的,数据报传输能到达对端全靠路由,因此它是一跳一跳地到达对端的,只要有一跳没有到达对端的路由,那么数据传输将失败,其实路由也是互联网的核心之一,实际上IP层提供的核心基本功能有两点,第一点是地址管理,第二点就是路由选路。

【转】[通俗易懂]深入理解TCP协议(下):RTT、滑动窗口、拥塞处理

前言

此文为系列文章的下篇,如果你对TCP不熟悉的话,请先看看上篇《[通俗易懂]深入理解TCP协议(上):理论基础》 。

上篇中,我们介绍了TCP的协议头、状态机、数据重传中的东西。但是TCP要解决一个很大的事,那就是要在一个网络根据不同的情况来动态调整自己的发包的速度,小则让自己的连接更稳定,大则让整个网络更稳定。在你阅读下篇之前,你需要做好准备,本篇文章有好些算法和策略,可能会引发你的各种思考,让你的大脑分配很多内存和计算资源,所以,不适合在厕所中阅读。

特别推荐:TCP/IP协议理论经典《TCP/IP详解 卷1:协议(在线阅读版)》、《TCP/IP详解 卷1:协议(CHM版)》。

TCP的RTT算法

从前面的TCP重传机制我们知道Timeout的设置对于重传非常重要:

  • 设长了,重发就慢,丢了老半天才重发,没有效率,性能差;
  • 设短了,会导致可能并没有丢就重发。于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。

而且,这个超时时间在不同的网络的情况下,根本没有办法设置一个死的值。只能动态地设置。 为了动态地设置,TCP引入了RTT——Round Trip Time,也就是一个数据包从发出去到回来的时间。这样发送端就大约知道需要多少的时间,从而可以方便地设置Timeout——RTO(Retransmission TimeOut),以让我们的重传机制更高效。 听起来似乎很简单,好像就是在发送端发包时记下t0,然后接收端再把这个ack回来时再记一个t1,于是RTT = t1 – t0。没那么简单,这只是一个采样,不能代表普遍情况。

1经典算法

RFC793中定义的经典算法是这样的:

  • 1)首先,先采样RTT,记下最近好几次的RTT值。
  • 2)然后做平滑计算SRTT( Smoothed

【转】[通俗易懂]深入理解TCP协议(上):理论基础

前言

TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面。所以学习TCP本身是个比较痛苦的过程,但对于学习的过程却能让人有很多收获。关于TCP这个协议的细节,我还是推荐你去看W.Richard Stevens的《TCP/IP 详解 卷1:协议》(当然,你也可以去读一下RFC793以及后面N多的RFC)。另外,本文我会使用英文术语,这样方便你通过这些英文关键词来查找相关的技术文档。

特别推荐:TCP/IP协议理论经典《TCP/IP详解 卷1:协议(在线阅读版)》、《TCP/IP详解 卷1:协议(CHM版)》。

本文目的

之所以想写这篇文章,目的有三个:

  • 一个是想锻炼一下自己是否可以用简单的篇幅把这么复杂的TCP协议描清楚的能力。
  • 另一个是觉得现在的好多程序员基本上不会认认真真地读本书,喜欢快餐文化,所以,希望这篇快餐文章可以让你对TCP这个古典技术有所了解,并能体会到软件设计中的种种难处。并且你可以从中有一些软件设计上的收获。
  • 最重要的希望这些基础知识可以让你搞清很多以前一些似是而非的东西,并且你能意识到基础的重要。

所以,本文不会面面俱到,只是对TCP协议、算法和原理的科普。

系列文章

我本来只想写一个篇幅的文章的,但是TCP真TMD的复杂,比C++复杂多了,这30多年来,各种优化变种争论和修改。所以,写着写着就发现只有砍成两篇:

更多参考资料:

【转】来自Google的TCP BBR拥塞控制算法解析

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dog250/article/details/52830576

写本文的初衷一部分来自于工作,更多的来自于发现国内几乎还没有中文版的关于TCP bbr算法的文章,我想抢个沙发。本文写于2016/10/15!
        本文的写作方式可能稍有不同,之前很多关于OpenVPN,Netfilter,IP路由,TCP的文章中,我都是先罗列了问题,然后阐述如何解决这个问题。但是本文不同!本文的内容来自于我十分厌恶的一个领域,其中又牵扯到我十分厌恶的一家公司-华夏创新(Appex),这些令我厌恶的东西让我不得不放弃很多的东西。所以,我不会先说业界遇到了什么问题,而是直接步入主题,阐述bbr算法的组成。我十分讨厌与人谈论关于TCP拥塞控制的话题,一方面是因为这个话题太过发散,任何人都可以说出自己的理由让人信服自己的忽悠人的算法,另一方面,我觉得我接触到的所有人当中并没有人真的懂这些(当然,我也不懂!而且比那些人更加不懂!),所以我宁可花些时间在预研或者研发上,我也不想跟人瞎逼逼或者听别人瞎逼逼。
        随便提出一个TCP拥塞算法,任何人都可以做到说它好,任何人也可以做到说它不好,因为没人真的懂网络,所以聊这些是没有意义的!TCP不是网络范畴的技术,它是控制论范畴的,TCP技术不属于网络技术!
        我的观点是,正确的做法只有一种,其它的都是错误的做法,都没有意义!

        国庆节前,我看到了bbr算法,发现它就是那个唯一正确的做法(可能有点夸张,但起码它是一个通往正确道路的起点!),所以花了点时间研究了一下它,包括其patch的注释,patch代码,并亲自移植了bbr patch到更低版本的内核,在这个过程中,我也产生了一些想法,作为备忘,整理了一篇文章,记如下,多年以后,再看TCP bbr算法的资料时,我的记录也算是中文社区少有的第一个吃螃蟹记录了,也算够了!

正文之前,给出本文的图例:

使用BBR之前

我希望更多的人试用这个算法,并且与我共享测试结果,包括但不限于算法的带宽利用率,抢占性等!特别是温州皮鞋产老板!这个算法并不是我写的,既然开源那就不应该封闭于任何公司或者个人,所以我有权在这里就我知道的东西述说一二。

        我深深地明白,我以下写的这些有很多理解不周到的地方,我也深深的明白很多传统学生出身的人不会告诉我那些疏漏,我指的是温州老板那样的人,因为他们几乎都是在索取而不分享,如果他们发现了我的疏漏,他们会默默记上一笔,到头来他们学会了我分享的东西,他们又改进了我的疏漏(但是并不告诉我!),他们又拥有自己独立学会的那些东西(他们也不会告诉我!),所以,最终,他们任何人都比我更加博学且高明!然而不幸的是,这就是我的目标,我并不在乎那些人,我甚至不会在乎自己!

        所以,赶紧试用bbr吧,赶紧改进吧,功劳是你的,虚无是我的!

BBR的组成

bbr算法实际上非常简单,在实现上它由5部分组成:

1.即时速率的计算

计算一个即时的带宽bw,该带宽是bbr一切计算的基准,bbr将会根据当前的即时带宽以及其所处的pipe状态来计算pacing rate以及cwnd(见下文),后面我们会看到,这个即时带宽计算方法的突破式改进是bbr之所以简单且高效的根源。计算方案按照标量计算,不再关注数据的含义。在bbr运行过程中,系统会跟踪当前为止最大的即时带宽。

2.RTT的跟踪

bbr之所以可以获取非常高的带宽利用率,是因为它可以非常安全且豪放地探测到带宽的最大值以及rtt的最小值,这样计算出来的BDP就是目前为止TCP管道的最大容量。bbr的目标就是达到这个最大的容量!…