TCP协议学习笔记

tcp报文段格式如下

图中保留字段有6位,看最新的书上面是4位,还有2位分别是CWRECE位。

源端口和目的端口

这两个值与IP头部的源和目标IP地址一起唯一的标识了每个连接。端口和IP地址的组合被称为端点或套接字

序列号

在发送用于建立连接的SYN之前,通信双方会选择一个初始序列号。初始序列号会随着时间而改变。因此每一个连接都拥有不同的序列号。文档指出,序列号可以被视为一个32位的计算器。该计算器的数值每4微秒+1
主要是防止序列号重复。

标识了TCP发送端发送到接收端的数据的一个字节,该字节代表着包含该序列号的报文段的数据中的第一个字节。这是一个32位的无符号数,到达2的32次方-1之后在循环回到0。

消耗一个序列号意味着使用重传进行可靠传输

确认序号

包含的值是该确认号的发送方期待接收到的下一个序列号。 即最后被成功接收的数据字节的序列号+1.

这个字段只有在ACK位被启用的情况下才有效。这个ACK位字段通常用于除了初始化和末尾报文段之外的所有报文段。

数据偏移(头部长度)

给出了头部的长度,以32位字节为单位,这个字段是必须的,因为选项字段的长度是可变的。作为一个4位的字段,TCP被限制为只能带60个字节的头部。而不带选项。大小是20字节。

窗口大小

TCP的流量控制由每一个端点使用窗口大小字段来通告一个窗口大小来完成。这个窗口大小是字节数,从ACK号指定的,也是接收方想要接收的那个字节开始。这是一个16位的字段,限制窗口大小65535字节,从而限制了TCP的吞吐量性能。

TCP校验和

覆盖了TCP的头部和数据以及头部中的一些字段。这个字段是强制的,由发送方进行计算和保存,然后由接收发验证。

CWR拥塞窗口减(发送方降低它的发送速度)

ECE(发送方接收了一个更早的拥塞通告)

URG 紧急(紧急字段有效很少被用到)

ACK 确认(确认号字段有效,连接建立以后一般都是开启状态)

PSH 推送

RST重置连接(连接取消,一般是因为错误)

SYN(用于初始化一个连接的同步序列号)

FIN 该报文段的发送发已经结束向对方发送数据

tcp选项

三次握手与四次挥手

一个TCP连接由4个元组组成,它们分别是2个IP地址和2个端口号。即一对端点或者套接字。

为了建立一个TCP连接,需要完成以下步骤:

  • 主动开启者(一般称为客户端)发送一个SYN报文段,并指明自己想要连接的端口号和它的客户端初始序列号(即为ISN(c))。通常客户端还会借此发送一个或者多个选项。

  • 服务器在收到客户端的SYN报文段后,也发送自己的SYN报文段作为响应,并包含它们初始序列号(记为SIN(s))。此外,为了确认客户端的SYN,服务器将其包含的ISN(c)数值+1后作为返回的ACK数值。因此,每发送一个SYN,序列号就会自动+1,这样如果出现丢失的情况,该SYN段将会重传。

  • 为了确认服务器的SYN,客户端将ISN(s)的数字+1作为返回的ACK数值。

通过上述的3个报文段就能够完成一个TCP连接的建立。它们也常称为三次握手

TCP协议规定通过发送一个FIN段来发起关闭操作。只有当连接双方都完成关闭操作以后,才构成一个完整关闭。

  • 连接的主动关闭者发送一个FIN段指明接收者希望看到的自己当前的序列号(K),FIN段还包含了一个ACK段用于确认对方最近一次发来的数据。

  • 连接的被动关闭者将K的数值+1作为响应的ACK值,以表示它已经成功接收到主动关闭者发送的FIN。

  • 被动关闭者将身份转变为主动关闭者,发送自己的FIN.

  • 为了完成连接的关闭,最后发送的报文段还包含一个ACK用于确认上一个FIN.值得注定的是,如果出现FIN丢失的情况,那么被动关闭方将重新传输直到收到一个ACK确认为止。

通过上诉的4个报文就能够完成一个TCP连接的关闭。他们也常称为四次挥手

TCP的状态转换图

tcp连接和断开过程中的状态变化

设置重传超时

TCP拥有两套独立机制来完成重传,一是基于时间,二是基于确认信息的构成。

TCP在发送数据的会设置一个计时器,若计时器超时仍未收到数据的确认信息,则会引发相应的超时或者基于计时器的重传操作,计时器超时称为重传超时(RTO)

另一种方式的重传称为快速重传,通常发生在没有延时的情况下,若TCP累计确认无法返回新的ACK,或者当ACK包含的选择确认信息(SACK)表明出现失序报文段时,快速重传会推断出现丢失包。在发送端认为接收端可能出现数据丢失时,需要决定发送新数据还是重传。

  • 使用往返时间(RTT)估计策略

    TCP在收到数据后会返回确认信息,因此可在该信息中携带一个字节的数据来测量传输该确认信息所需要的时间。每个此类的测量结果称为RTT样本。TCP首先需要根据一段时间内的样本值建立好的估计值。然后使用计算公式根据RTT估值得到RTO值。

    选择一组RTT样本的样本均值作为真实的RTT是最有可能的,注意这个均值很自然的会随着时间而改变,因为通信穿过的网络的路径可能改变。

快速重传

快速重传机制基于接收端的反馈信息来引发重传,而非重传计时器的超时。因此与超时重传相比,快速重传能更加及时有效的修复丢包情况。

当接收到失序报文段时,TCP需要立即生成确认信息(重复ACK)。并且失序情况表明在后续数据到达前出现了丢段,即接收端缓存出现了空缺。发送端的工作即为尽快的,高效的填补空缺。所以当失序数据到达是,重复ACK应该立即返回,不能延迟发送。

当重复ACK的数量达到一定的数目(称为重复ACK阈值)时,快速重传机制才会被触发。

带选择确认的重传

ACK号与接收端缓存中的的其他数据之间的间隔称为空缺。序列号高于空缺的数据称为失序数据,因为这些数据与之前接收的序列号不连续。

TCP发送端的任务是通过重传丢失数据来填补接收端缓存中的空缺,但同时也要尽可能保证不重传 已正确接收到的数据。在很多环境下,合理采用SACK信息能更快的实现空缺填补,且能减少不必要的重传,原因在于其在一个RTT内能获知多个空缺。当采用SACK选项时,一个ACK可包含三四个告知失序数据的SACK信息。每个SACK信息包含32位的序列号,代表接收端存储的失序数据的起始至最后一个序列号(+1)。

数据流与窗口管理

可以采用可变滑动窗口来实现流量控制

发送窗口结构

TCP发送端滑动窗口结构记录了已确认,在传以及还未传的数据的序列号。提供窗口的大小控制由接收端返回的ACK中的窗口大小字段控制

随着时间的推移,当接收到返回的数据ACK,滑动窗口也随之右移。窗口两端的相对运动使得窗口增大或减小。可用三个术语来描述窗口左右边界的运动。

  • 关闭:即窗口左边界右移。当已发送数据得到ACK确认时,窗口会减小。
  • 打开:即窗口右边界右移,使得可发送数据增大。当已确认数据得到处理,接收端可用缓存增大,窗口也随之变大。
  • 收缩:即窗口右边界左移。

接收窗口结构

该窗口结构记录了已接收并确认的数据,以及它能够接收的最大序列号。该窗口可以保证其接收数据的正确性。特别是接收端希望避免存储重复的已接收和确认的数据,以及避免存储不应该接收的数据。

拥塞控制

路由器因无法处理高速率到达的流量而被迫丢弃数据信息的现象称为拥塞。

在有线网络中,出现在路由器或者交换机中的拥塞是造成丢包的主要原因;
在无线网络中,传输和接收错误是导致丢包的重要因素。

反映网络传输能力的变量称为拥塞窗口,记做(cwnd).

慢启动

当一个新的TCP连接建立或者检测到由重传超时(RTO)导致的丢包时,需要执行慢启动。TCP发送端长时间处于空闲状态也可能调用慢启动算法。慢启动的目的是,是TCP在用拥塞避免探寻更多可用带宽之前得到cwnd值,以及帮助TCP建立ACK时钟。通常,TCP在建立新连接时执行慢启动,直至有丢包时,执行拥塞避免算法进入稳定状态。

在传输初始阶段,由于未知网络传输能力,需要缓慢探测可用传输资源,防止短时间内大量数据注入导致拥塞。慢启动算法正是针对这一问题而设计。在数据传输之初或者重传计时器检测到丢包后,需要执行慢启动

拥塞避免

为了得到更多的传输资源而不至于影响其他连接传输,TCP实现了拥塞避免算法。一旦确立慢启动阈值,TCP会进入拥塞避免阶段,cwnd每次的增长值近似于成功传输的数据段大小。这种随时间线性增长的方式于慢启动的指数增长相比缓慢许多。

慢启动和拥塞避免的选择

慢启动阈值(ssthresh)和cwnd的关系决定了采用慢启动还是拥塞避免的界限。当cwndssthresh时,需要执行拥塞避免,而当两者相等时,任何一种算法都可以。

慢启动和拥塞控制之间最大的却别在于,cwnd怎样增长。慢启动是指数增长,拥塞避免时是线性增长。

TCP保活机制(keepalive)

保活机制是一种不影响数据流内容的情况下探测对方的方式。它是由一个保活计时器实现的。当计时器被激活,连接一端将发送一个保活报文,另一端接收到报文的同时会发送一个ACK作为响应。

如果在一段时间(保活时间keepalive time)内连接处于非活动状态,开启保活功能的一端将向对方发送一个保活探测报文。如果发送端没有收到响应报文,那么经过一个已经提前配置好的保活时间间隔(keepalive interval),将继续发送保活探测报文,直到发送探测报文的次数达到保活探测数(keepalive probe)。这是对方主机将被确认为不可到达,连接也将中断。

保活探测报文为一个空报文段(或只包含一个字节),他的序列号等于对方主机发送的ACK报文的最大序列号减1.因为这一序列号的数据已经被成功接收,所以不会对到达的报文段造成影响。