当前位置:   article > 正文

TCP(传输控制协议)_头部长度 该字段占用4位,用来表示tcp报文首部的长度,单位是4bit位。其值所表示的

头部长度 该字段占用4位,用来表示tcp报文首部的长度,单位是4bit位。其值所表示的

TCP 最主要的特点

  • TCP 是应用程序在使用 TCP 协议之前,必须先建立 TCP 连接。 在传送数据完毕后,必须释放已经建立的 TCP 连接面向连接的运输层协议
  • 每一条 TCP 连接只能有两个,每一条 TCP 连接只能是(一对一)点对点
  • TCP 提供的服务。 通过 TCP 连接传送的数据,无差错、不丢失、不重复,并且按序到达可靠交付
  • TCP 允许通信双方的应用进程在任何时候都能发送数据。 TCP 连接的两端都设有发送缓存和接受缓存,用来临时存放双向通信的数据全双工通信
  • 面向字节流 TCP 中的“流”指的是流入到进程或从进程流出的字节序列

简单概括:

  • 面向连接
  • 点对点传输
  • 可靠传输
  • 拥塞控制
  • 面向字节流

面向字节流

“面向字节流”的含义是:虽然应用程序和 TCP 的交互式一次一个数据块(大小不等),但 TCP 把应用程序交下来的数据仅仅看成是一连串的。 TCP 并不知道所传送的字节流的含义无结构的字节流

TCP 不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系

例如,发送方应用程序交给发送方的 TCP 共10个数据块,但接收方的 TCP 可能只用了4个数据块就把收到的字节流交付上层的应用程序

接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样。 接收方的应用程序必须有能力识别收到的字节流,把它还原成有意义的应用层数据

TCP 和 UDP 在发送报文时采用的方式完全不同。 TCP 并不关心应用进程一次把多长的报文发送到 TCP 的缓存中,而是根据对方给出的窗口值和当前网络拥塞的程度来决定一个报文段应包含多少个字节(UDP 发送的报文长度是应用进程给出的)。 如果应用进程传送到 TCP 缓存的数据块太长,TCP 就可以把它划分短一些再传送。 如果应用进程一次只发来一个字节,TCP 也可以等待积累有足够多的字节后再构成报文段发送出去

TCP 的连接

TCP 的许多特性都与 TCP 是面向连接的这个基本特性有关连接最基本的抽象

TCP 连接的端点叫做,根据 RFC 793 的定义:端口号拼接到(concatenated with) IP 地址即构成了套接字套接字(socket)或插口

套接字 socket = (IP 地址:端口号)

每一条 TCP 连接唯一地被通信两端的两个端点(即两个套接字)所确定

TCP 连接 ::= {socket1, socket2} = {(IP1: port1), (IP2: port2)}

TCP 连接就是由协议软件所提供的一种抽象。 ,即( : )。 同一个 IP 地址可以有多个不同的 TCP 连接,而同一个端口号也可以出现在多个不同的 TCP 连接中TCP 连接的端口是个很抽象的套接字IP地址端口号

易混淆的 socket

同一个名词 socket 却可表示多种不同的意思,以下 socket 的意思跟本文中所引用的 RFC 793 定义的 socket(指端口号拼接到 IP 地址)不同

  • 允许应用程序访问连网协议的,即运输层和应用层之间的接口,称为 socket API,并简称为 socket应用编程接口 API(Application Programming Interface)
  • 在 socket API 中使用的一个也叫做 socket函数名
  • 调用 socket 函数的称为 socket,如“创建一个数据报 socket”端点
  • 调用 socket 函数时,其称为 socket 描述符,可简称为 socket返回值
  • 在操作系统内核中连网协议的 Berkeley 实现,称为 socket 实现

可靠传输的工作原理

理想的传输条件

理想的传输条件有以下两个特点

  • 传输信道不产生差错
  • 不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据

实际的网络不具备以上两个理想条件。需要使用一些可靠的传输协议,当出现差错时让发送方重传出现差错的数据,同时在接收方来不及处理收到的数据时,及时告诉发送方适当减低发送数据的速度。这样,不可靠的传输信道就能够实现可靠传输了

停止等待协议

全双工通信的双方既是发送方也是接收方。把传送的数据单元都称为分组。“停止等待”就是每发完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组

无差错情况

出现差错

只要超过一段时间没有收到确认,就认为刚才发送的分组丢失了,因而重传前面发送过的分组。这就叫做。要实现超时重传,就要在每发送完一个分组时设置一个超时重传超时计时器

  • 发送完一个分组后,(在发生超时重传时使用)。只有在收到相应的确认后才能清除暂时保留的分组副本必须暂时保留已发送的分组的副本
  • 分组和确认分组都必须进行。这样才能明确是哪一个发送出去的分组收到了确认,而哪一个分组还没有收到确认编号
  • 超时计时器的重传时间应当比数据在分组传输的平均往返时间更长一些

确认丢失和确认迟到

使用上述的确认和重传机制,我们就可以不可靠的传输网络上实现可靠的通信

重传的请求是自动进行的。接收方不需要请求发送方重传某个出错的分组像上述的,这种可靠传输协议常称为自动重传请求 ARQ(Automatic Repeat reQuest)

信道利用率

停止等待协议的优点是简单,但缺点是信道利用率太低

为了提高传输效率,发送方可以不使用低效率的停止等待协议,而是采用流水线传输就是发送方可连续发送多个分组,不必每发完一个分组就停顿下来等待对方的确认。这样可使信道上一直有数据不间断地在传送。这种传输方式可以获得很高的信道利用率流水线传输

连续 ARQ 协议

位于发送窗口内的5个分组都可以连续发送出去,而不需要等待对方的确认。可以提高信道利用率

接收方一般都是采用的方式。接收方不需要对收到的分组逐个发送确认,而是在收到几个分组后,累积确认对按序到达的最后一个分组发送确认

积累确认有优点也有缺点。优点是:容易实现,即使确认丢失也不必重传。缺点是不能向发送方反映出接收方已经正确收到的所有分组的信息

TCP协议的报文格式


在TCP/IP协议栈中,IP协议层只关心如何使数据能够跨越本地网络边界的问题,而不关心数据如何传输。整体TCP/IP协议栈,共同配合一起解决数据如何通过许许多多个点对点通路,顺利传输到达目的地。一个点对点通路被称为一“跳”(hop),通过TCP/IP协议栈,网络成员能够在许多“跳”的基础上建立相互的数据通路。

传输层TCP协议提供了一种面向连接的、可靠的字节流服务,其数据帧格式,大致如下图所示:


图:传输层TCP协议的数据帧格

一个传输层TCP协议的数据帧,大致包含以下字段:

(一)源端口号
源端口号表示报文的发送端口,占16位。源端口和源IP地址组合起来,可以标识报文的发送地址。

(二)目的端口号
目的端口号表示报文的接收端口,占16位。目的端口和目的IP地址相结合,可以标识报文的接收地址。

TCP协议是基于IP协议的基础上传输的,TCP报文中的源端口号+源IP,与TCP报文中的目的端口号+目的IP一起,组合起来唯一性的确定一条TCP连接。

(三)序号(Sequence Number)
TCP传输过程中,在发送端出的字节流中,传输报文中的数据部分的每一个字节都有它的编号。序号(Sequence
Number)占32位,发起方发送数据时,都需要标记序号。

序号(Sequence Number)的语义与SYN控制标志(Control
Bits)的值有关。根据控制标志(Control Bits)中的SYN是否为1,序号(Sequence
Number)表达不同的含义:

(1)当SYN = 1时,当前为连接建立阶段,此时的序号为初始序号ISN((Initial Sequence
Number),通过算法来随机生成序号;

(2)当SYN = 0时在数据传输正式开始时,第一个报文的序号为 ISN +
1,后面的报文的序号,为前一个报文的SN值+TCP报文的净荷字节数(不包含TCP头)。比如,如果发送端发送的一个TCP帧的净荷为12byte,序号为5,则发送端接着发送的下一个数据包的时候,序号的值应该设置为5+12=17。

在数据传输过程中,TCP协议通过序号(Sequence
Number)对上层提供有序的数据流。发送端可以用序号来跟踪发送的数据量;接收端可以用序号识别出重复接收到的TCP包,从而丢弃重复包;对于乱序的数据包,接收端也可以依靠序号对其进行排序。

(四)确认序号(Acknowledgment Number)
确认序号(Acknowledgment
Number)标识了报文接收端期望接收的字节序列。如果设置了ACK控制位,确认序号的值表示一个准备接收的包的序列码,注意,它所指向的是准备接收的包,也就是下一个期望接收的包的序列码。

举个例子,假设发送端(如Client)发送3个净荷为1000byte、起始SN序号为1的数据包给Server服务端,Server每收到一个包之后,需要回复一个ACK响应确认数据包给Client。ACK响应数据包的ACK
Number值,为每个Client包的为SN+包净荷,既表示Server已经确认收到的字节数,还表示期望接收到的下一个Client发送包的SN序号,具体的ACK值如下图左边的正常传输部分所示。


图:传输过程的确认序号(Acknowledgment Number)值示例图

 

在上图的左边部分,Server第1个ACK包的ACK
Number值为1001,是通过Client第1个包的SN+包净荷=1+1000计算得到,表示期望第2个Client包的SN序号为1001;Server第2个ACK包的ACK
Number值为2001,为Client第2个包的SN+包净荷=2001,表示期望第3个Server包的SN为2001,以此类推。

如果发生错误,假设Server在处理Client的第二个发送包异常,Server仍然回复一个ACK
Number值为1001的确认包,则Client的第二个数据包需要重复发送,具体的ACK值如上图右边的正常传输部分所示。

只有控制标志的ACK标志为1时,数据帧中的确认序号ACK
Number才有效。TCP协议规定,连接建立后,所有发送的报文的ACK必须为1,也就是建立连接后,所有报文的确认序号有效。如果是SYN类型的报文,其ACK标志为0,故没有确认序号。

(五)头部长度
该字段占用4位,用来表示TCP报文首部的长度,单位是4bit位。其值所表示的并不是字节数,而是头部的所含有的32bit的数目(或者倍数),或者4个字节的倍数,所以TCP头部最多可以有60字节(4*15=60)。没有任何选项字段的TCP头部长度为20字节,所以其头部长度为5,可以通过20/4=5计算得到。

(六)预留6位
头部长度后面预留的字段长度为6位,作为保留字段,暂时没有什么用处。

(七)控制标志
控制标志(Control
Bits)共6个bit位,具体的标志位为:URG、ACK、PSH、RST、SYN、FIN。6个标志位的说明,如下表所示。

表:TCP报文控制标志(Control Bits)说明

 
标志位说明
URG占1位,表示紧急指针字段有效。URG位指示报文段里的上层实体(数据)标记为“紧急”数据。当URG=1时,其后的紧急指针指示紧急数据在当前数据段中的位置(相对于当前序列号的字节偏移量),TCP接收方必须通知上层实体。
ACK

占1位,置位ACK=1表示确认号字段有效;TCP协议规定,接建立后所有发送的报文的ACK必须为1;当ACK=0时,表示该数据段不包含确认信息。当ACK=1时,表示该报文段包括一个对已被成功接收报文段的确认序号Acknowledgment Number,该序号同时也是下一个报文的预期序号。

PSH占1位,表示当前报文需要请求推(push)操作;当PSH=1时,接收方在收到数据后立即将数据交给上层,而不是直到整个缓冲区满。
RST占1位,置位RST=1表示复位TCP连接;用于重置一个已经混乱的连接,也可用于拒绝一个无效的数据段或者拒绝一个连接请求。如果数据段被设置了RST位,说明报文发送方有问题发生。
SYN占1位,在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1。 综合一下,SYN置1就表示这是一个连接请求或连接接受报文。
FIN占1位,用于在释放TCP连接时,标识发送方比特流结束,用来释放一个连接。当 FIN = 1时,表明此报文的发送方的数据已经发送完毕,并要求释放连接。
在连接建立的三次握手过程中,若只是单个SYN置位,表示的只是建立连接请求。如果SYN和ACK同时置位为1,表示的建立连接之后的响应。

 

(八)窗口大小:
长度为16位,共2个字节。此字段用来进行流量控制。流量控制的单位为字节数,这个值是本端期望一次接收的字节数。

(九)校验和:
长度为16位,共2个字节。对整个TCP报文段,即TCP头部和TCP数据进行校验和计算,接收端用于对收到的数据包进行验证。

(十)紧急指针:
长度为16位,2个字节。它是一个偏移量,和SN序号值相加表示紧急数据最后一个字节的序号。

以上十项内容是TCP报文首部必须的字段,也称固有字段,长度为20个字节。接下来是TCP报文的可选项和填充部分。

(十一)可选项和填充部分
可选项和填充部分的长度为4n字节(n是整数),该部分是根据需要而增加的选项。如果不足4n字节,要加填充位,使得选项长度为32位(4字节)的整数倍,具体的做法是在这个字段中加入额外的零,以确保TCP头是32位(4字节)的整数倍。

最常见的选项字段是MSS(Maximum Segment
Size最长报文大小),每个连接方通常都在通信的第一个报文段(SYN标志为1的那个段)中指明这个选项字段,表示当前连接方所能接受的最大报文段的长度。

由于可选项和填充部分不是必须的,所以TCP报文首部最小长度为20个字节。

至此,TCP报文首部的字段,就全部介绍完了。TCP报文首部的后面,接着的是数据部分,不过数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有TCP首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据,比如在处理超时的过程中,也会发送不带任何数据的报文段。

TCP 可靠传输的实现

以字节为单位的滑动窗口

发送窗口构造

TCP 的滑动窗口是以字节为单位的。假定 A 收到了 B 的确认报文段,其中窗口是20字节,而确认号是31(这表明 B 期望收到的下一个序号是31,而序号30为止的数据已经收到了)。根据这两个数据,A 就构造出自己的发送窗口发来

发送窗口标识:在没有收到 B 的确认的情况下,A 可以连续把窗口内的数据都发送出去。凡是已经发送出去的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用

发送窗口变化

发送窗口的位置由窗口前沿和后沿的位置共同确定。发送窗口后沿的变化情况有两种,即不动(没有收到新的确认)和前移(收到了新的确认)。发送窗口后沿不可能向后移动,因为不能撤销已收到的确认

发送窗口前沿通常是不断向前移动,但也有可能不动。这对应于两种情况:

  • 一是没有收到信的确认,对应通知的窗口大小也不变
  • 二是收到了新的窗口单对方通知的窗口缩小了,使得发送窗口前沿正好不动

发送窗口前沿也有可能。这发生在对方通知的窗口缩小了。但 TCP 的标准。因为很可能发送方在收到这个通知以前已经发生了窗口中的许多数据,现在又要收缩窗口,不让发送这些数据,这样就会产生一些错误向后收缩强烈不赞成这样做

要描述一个发送窗口的状态需要三个指针:P1,P2,P3。指针都指向字节的序号。这三个指针指向的几个部分的意义如下:

  • 小于 P1 的是已发送并已收到确认的部分,而大于 P3 的是不允许发送的部分
  • P3 - P1 = A 的发送窗口
  • P2 - P1 已发送但尚未收到确认的字节数
  • P3 - P2 允许发送但当前尚未发送的字节数(又称为或可用窗口有效窗口)

B 的接收窗口大小是20。在接收窗口外面,到30号为止的数据是已经发送过确认,并且已经交付主机了。因此在 B 可以不再保留这些数据。接收窗口内的序号(31\~50)是允许接收的。在上图中,B 收到了序号为32和33的数据。这些数据没有按序到达,因为序号为31的数据没有收到(也许丢失了,也许滞留在网络中的某处)。请注意,B 只能对按序收到的数据中的最高序号给出确认,因此 B 发送的确认报文段中的确认号仍然是31(即期望收到的序号),而不是32或33

现在假定 B 收到了序号为31的数据,并把序号为31\~33的数据交付主机,然后 B 删除这些数据。接着把接收窗口向前移动3个序号,同时给 A 发送确认,其中窗口值仍为20,但确认号是34.这表明 B 已经收到了到序号33为止的数据。B 还收到了序号为37,38和40的数据,但这些都没有按序到达,只能先暂存在接收窗口中。A 收到 B 的确认后,就可以把发送窗口向前滑动3个序号,但指针 P2 不动。现在 A 的可用窗口增大了,可发送的序号范围是42\~53

A 在继续发送完序号42\~53的数据后,指针 P2 向前移动和 P3 重合。发送窗口内的序号都已用完,但还没有再收到确认。由于 A 的发送窗口已满,可用窗口已减小到零,因此必须停止发送。发送窗口内所有的数据都已正确到达 B,B 也早已发出了确认。但所有这些确认都滞留在网络中。在没有收到 B 的确认时,A 不能猜测:“或许 B 收到了吧!”为了保证可靠传输,A 只能认为 B 还没有收到这些数据。于是,A 在经过一段时间后(由超时计时器控制)就重传这部分数据,重新设置超时计时器,知道收到 B 的确认为止。如果 A 收到确认号落在发送窗口内,那么 A 就可以发送窗口继续向前滑动,并发送新的数据

缓存和窗口

发送方维持的发送缓存和发送窗口,以及接收方维持的接收缓存和接收窗口

发送缓存用来暂时存放:

  • 发送应用程序传送给对方 TCP 准备发送的数据
  • TCP 已发送出但尚未收到确认的数据

已被确认的数据应当从发送缓存中删除,因此发送缓存和发送窗口的后沿是重合的。 发送应用程序必须控制写入缓存的速率,不能太快,否则发送缓存就会没有存放数据的空间

接收缓存用来暂时存放:

  • 按序到达的、但尚未被接收应用程序读取的数据
  • 未按序到达的数据

收到的分组被检测出有差错,则丢弃。 接收应用程序来不及读取收到的数据,接收缓存最终就会被填满,使接收窗口减小到零。 接收应用程序能够及时从接收缓存中读取收到的数据,接收窗口就可以增大,最大亦不能超过接收缓存的大小

要点小结:

  • 虽然 A 的发送窗口是根据 B 的接收窗口设置的,但在同一时刻,A 的发送窗口并不总是和 B 的接收窗口一样大。 通过网络传送窗口值需要经历一定的时间滞后,该时间并不确定的
  • 对于不按序到达的数据,TCP 通常是先临时存放在接收窗口,等字节流中所缺少的字节收到后,在按序交付上层的应用进程
  • TCP 要求接收方必须有累积确认的功能,这样可以减少传输开销

超时重传时间的选择

TCP 的发送方在规定的时间内没有收到确认就要重传已发送的报文段。 这种重传的概念是很简单的,但重传时间的选择却是 TCP 最复杂的问题之一

由于 TCP 的下层是互联网环境,发送的报文段可能只经过一个高速率的局域网,也可能经过多个低速率的网络,并且每个 IP 数据报所选择的路由还可能不同。 如果把超时重传时间设置得太短,就会引起很多报文段的必须要的重传,使网络负荷增大。 但若把超时重传时间设置的过长,则又使网络的空闲时间增大,减低了传输效率

TCP 采用了一种自适应算法,它记录一个报文段发出的时间,以及收到相应的确认的时间。 这两个时间之差就是报文段的往返时间 RTT

新的 RTTs = (1 - α) x (旧的 RTTs) + α x (新的 RTT 样本)

RTT:报文段往返时间 RTTs:加权平均往返时间 α: 0 ≤ α < 1,RFC 6298 推荐的 α 值为 1/8,即 0.125

RTO = RTT + 4 x RTTD

RTO:超时重传时间 RTTD:RTT 的偏差的加权平均值

新的 RTTD = (1 - β) x (旧的 RTTD) + β x | RTTs - 新的 RTT 样本|

β:小于1的系数,推荐值是 1/4,即 0.25

TCP 流量控制

利用滑动窗口实现流量控制

流量控制(flow control):让发送方的发送速率不要太快,要让接收方来得及接收

利用滑动窗口机制可以很方便地在 TCP 连接上实现对发送方的流量控制

发送方的发送窗口不能超过接收方给出的接收窗口的数值。 TCP 的窗口单位是字节,不是报文段

避免死锁:TCP 为每一个连接设有一个。 只要 TCP 连接的一方收到对方的零窗口通知,就启动持续计时器。 若持续计时器设置的时间到期,就发送一个零窗口(仅携带1字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值。 如果窗口仍是零,那么收到这个报文段的一方就重新设置持续计时器。 如果窗口不是零,那么死锁的僵局就可以打破了持续计时器(persistence timer)探测报文段

TCP 的传输效率

发送机制

  • TCP 维持一个变量,它等于。 只要缓存中存放的数据达到 MSS 字节时,就组装成一个 TCP 报文段发送出去最大报文段长度 MSS
  • 由发送方的应用进程指明要求发送报文段,即 TCP 支持的操作推送(push)
  • 发送方的一个计时器期限到了,这时把当前已有的缓存数据装入报文段(但长度不能超过 MSS)发送出去

Nagle 算法

在 TCP 的实现中广泛使用 Nagle 算法

若发送应用进程把要发送的数据逐个字节地送到 TCP 的发送缓存,则发送方就把第一个数据字节先发送出去,把后面到达的数据字节都缓存起来。 当发送方收到对第一个数据字符的确认后,再把发送缓存中的所有数据组装成一个报文段发送出去,同时继续对随后到达的数据进行缓存。 只有在收到对前一个报文段的确认后才继续发送下一个报文段。 当数据达到较快而网络速率较慢时,用这样的方法可明显地减少所用的网络宽带。 Nagle 算法还规定,当到达的数据已达到发送窗口大小的一半或已达到报文段的最大长度时,就立即发送一个报文段。 这样可以有效提高网络的吞吐量

糊涂窗口综合征

TCP 接收方的缓存已满,仅剩一个字节,并还将保持这种状态持续一段时间。 导致发送方只能发送一个字节。 导致网络的效率很低

为了解决这个问题,可以,使得或者接受缓存已有足够空间容纳一个最长的报文段,或者。 只要出现这两种情况之一,接收方就发出确认报文,并向发送方通知当前的窗口大小。 发送方也不要发送大小的报文段,而是把数据积累成足够大的报文段,或达到接收方缓存的空间的一半大小让接收方等待一段时间等到接受缓存已有一半空闲的空间

TCP 的拥塞控制

拥塞控制的一般原理

在计算机网络中的链路容量(即宽带)、交换结点中的缓存和处理机等,都是网络资源。 在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。 这种情况就叫做(congestion)拥塞

拥塞控制就是。 拥塞控制所要做的都是一个前提,就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载网络能够承受现有的网络负荷

TCP 的拥塞控制方法

TCP 进行拥塞控制的算法有四种,即(slow-start)、(congestion avoidance)、(fast retransmit)和(fast recovery)慢开始拥塞避免快重传快恢复

慢开始

当主机开始发送数据时,由于并不清楚网络的负荷情况,如果立即把大量数据字节注入到网络,就有可能引起网络发生拥塞。 经验证明,较好的方法是先探测一下,即,也就是说,由小到大逐渐增大发送窗口由小到大逐渐增大拥塞窗口数值

cwnd:发送方的拥塞窗口,开始发送方设置 cwnd = 1

拥塞避免

让拥塞窗口 cwnd 缓慢地增大,即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加1,而不是像慢开始阶段那样加倍增加。 因此在拥塞避免阶段就有“” AI(Additive Increase)的特点。 这表明在拥塞避免阶段,拥塞窗口 cwnd ,比慢开始算法的拥塞窗口增长速率缓慢得多加法增大按线性规律缓慢增长

“拥塞避免”并非完全能够避免拥塞,而是把拥塞窗口控制为按线性规律增长,使网络比较不容易出现拥塞

在执行慢开始算法时,发送方每收到一个队新报文段的确认 ACK,就把拥塞窗口值加1,然后开始下一轮的传输。 因此拥塞窗口 cwnd 随着传输轮次按指数规律增长。 当拥塞窗口 cwnd 增长到慢开始门限值 ssthresh 时,就改成执行拥塞避免算法,拥塞窗口按线性规律增长

ssthresh:慢开始门限,一般的,会有一个初始值,下图中为16个报文段

当拥塞窗口 cwnd = 24 时,网络出现了超时,发送方判断为网络拥塞。 于是调整门限值 ssthresh = cwnd / 2 = 12,同时设置拥塞窗口 cwnd = 1,进入慢开始阶段

快重传

采用快重传算法可以让发送方。 快重传算法首先要求接收方不要等待自己发送数据时才进行捎带确认,而是要,即使收到了也要立即发出对已收到的报文段的重复确认尽早知道发生了个别报文段的丢失立即发送确认失序的报文段

快恢复

发送发知道当前只是丢失了个别的报文段。 于是不启动慢开始,而是执行算法。 这时,发送方调整门限值 ssthresh = cwnd / 2 = 8,同时设置拥塞窗口 cwnd = ssthresh = 8,并开始执行拥塞避免算法快恢复

TCP Reno 版本:区别于老的 TCP Tahao 版本

TCP 的运输连接管理

TCP 是面向连接的协议。 运输连接是用来传送 TCP 报文的。 TCP 运输连接的建立和释放是每一次面向连接的通信中必不可少的过程。 运输连接有三个阶段,、和。 运输的连接管理就是使运输连接的建立和释放都能够正常地进行连接建立数据传送连接释放

在 TCP 连接建立过程中要解决以下三个问题:

  • 要使每一方能够确知对方的存在
  • 要允许双方协商一些参数(最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量等)
  • 能够对运输实体资源(缓存大小、连接表中的项目等)进行分配

TCP 的连接建立

TCP 建立连接的过程叫做握手,握手需要在客户和服务器之间交换三个 TCP 报文段

连接建立过程

  1. 最初客户/服务器的 TCP 进程都处于 状态。 在本实例中,A ,而 B CLOSED(关闭)主动打开连接被动打开连接
  2. B 的 TCP 服务器进程先创建 TCB,并处于 状态,等待客户的连接请求传输控制块LISTEN(收听)
  3. A 的 TCP 客户进程创建 TCB。 并向 B 发出连接请求报文段,首部中的同部位 SYN = 1,选择一个初始序号 seq = x。 TCP 客户端进程进入 状态。 TCP 规定,SYN 报文段(即 SYN = 1 的报文段)不能携带数据,但要传输控制模块SYN-SENT(同步已发送)消耗一个序号
  4. B 收到连接请求报文段后,如同意建立连接,则向 A 发送确认。 在确认报文段中应把 SYN 位和 ACK 位都置1,确认号是 ack = x + 1,同时也为自己选择一个初始序号 seq = y。 这时 TCP 服务器进程进入 状态。 这个报文段也不能携带数据,但同样SYN-RCVD(同步收到)要消耗掉一个序号
  5. TCP 客户进程收到 B 的确认后,还要向 B 给出确认。 确认报文段的 ACK 置1,确认号 ack = y + 1,而自己的序号 seq = x + 1。 TCP 的标准规定,ACK 报文段可以携带数据。 但,在这种情况下,下一个数据报文段的序号仍是 seq = x + 1。 这时,TCP 连接已经建立,A 进入 状态如果不携带数据则不消耗序号ESTABLISHED(已建立连接)
  6. 当 B 收到 A 的确认后,也进入 状态ESTABLISHED
传输控制块 TCB(Transmission Control Block)存储了每一个连接中的一些重要信息,如:TCP 连接表,指向发送和接收缓存的指针,指向重传队列的指针,当前的发送和接收序号等等

四报文握手

B 发送给 A 的报文段,可拆成两个报文段。 先发送一个确认报文段(ACK = 1,ack = x + 1),然后再发送一个同步报文段(SYN = 1,seq = y)。 这样的过程就变成了,与三报文握手效果一致四报文握手

异常情况

为什么 A 最后还要发送一次确认呢? 这主要是为了防止已失效的连接请求报文段突然又传到了 B,因而产生错误

正常情况:A 发出连接请求,但因连接请求报文丢失而未收到确认。 于是 A 再重传一次连接请求。 后来收到了确认,建立了连接。 数据传输完毕后,就释放了连接。 A 共发送了两个连接请求报文段,其中第一个丢失,第二个到达了 B,没有“已失效的连接请求报文段”

异常情况:A 发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达 B。 本来这是一个早已失效的报文段。 但 B 收到此失效的连接请求报文段后,就误认为是 A 又发出一次新的连接请求。 于是就向 A 发出确认报文段,同意建立连接。 假定不采用报文握手,那么只要 B 发出确认,新的连接就建立了。

现在 A 并没有发出建立连接的请求,因此不会理睬 B 的确认,也不会向 B 发送数据。 但 B 却以为新的运输连接已经建立了,并一直等待 A 发来数据。 B 的。
采用三报文握手的办法,可以防止上述现象的发生许多资源就这样被浪费了

TCP 的连接释放

连接释放过程

  1. A 的应用进程先向其 TCP 发出连接释放报文段,并停止再发送数据,主动关闭 TCP 连接。 A 把连接释放报文段首部的终止控制位 FIN 置1,其序号 seq = u,它等于前面已传送过的数据的最后一个字节的序号加1。 这时 A 进入 状态,等待 B 的确认。 TCP 规定,FIN 报文段即使不携带数据,也消耗一个序号FIN-WAIT-1(终止等待1)
  2. B 收到连接释放报文段后即发出确认,确认号是 ack = u + 1,而这个报文段自己的序号是 v,等于 B 前面已传送过的数据的最后一个字节的序号加1。 B随即进入 状态。 TCP 服务器进程这时应通知高层应用进程,因而从 A 到 B 这个方向的连接就释放了,这时的 TCP 连接处于 状态,即 A 已经没有数据要发送了,但 B 若发送数据,A 仍要接收。 也就是说,从 B 到 A 这个方向的连接并未关闭,这个状态可能会持续一段时间CLOSE-WAIT(关闭等待)半关闭(half-close)
  3. A 收到来自 B 的确认后,就进入 状态,等待 B 发出的连接释放报文段FIN-WAIT-2(终止等待2)
  4. 若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放连接。 这时 B 发出的连接释放报文段必须使 FIN = 1。 现假定 B 的序号为 w(在半关闭状态 B 可能又发送了一些数据)。 B 还必须重复上次已发送过的确认号 ack = u + 1。 这时 B 就进入 状态,等待 A 的确认LAST-ACK(最后确认)
  5. A 在收到 B 的连接释放报文段后,必须对此发出确认。 在确认报文段中把 ACK 置1,确认号 ack = w + 1,而自己的序号是 seq = u + 1(根据 TCP 标准,前面发送过的 FIN 报文段要消耗一个序号)。 然后进入到 状态。 此时 TCP 连接还没有释放掉。 必须经过设置的时间2MSL后,A 才进入到 状态TIME-WAIT(时间等待)时间等待计时器(TIME-WAIT timer)CLOSED
  6. 当 A 撤销相应的传输控制块 TCB 后,就结束了这次的 TCP 连接
时间 MSL 叫做(Maximum Segment Lifetime),RFC 793建议设为2分钟。 但这完全是从工程上来考虑的,对于现在的网络,MSL = 2分钟可能太长了一些最长报文段寿命

TIME-WAIT 等待时间

为什么 A 在 TIME-WAIT 状态必须等待 2MSL 的时间呢?

为了保证 A 发送的最后一个 ACK 报文段能够到达 B。 这个 ACK 报文段有可能丢失,因而使处在 LAST-ACK 状态的 B 收不到对已发送的 FIN + ACK 报文段的确认。 B 会超时 重传这个 FIN + ACK 报文段,而 A 就能在 2MSL 时间内收到这个重传的 FIN + ACK 报文段。 接着 A 重传一次确认,重新启动 2MSL 计时器。 最后,A 和 B 都正常进入到 CLOSED 状态。 如果 A 在 TIME-WAIT 状态不等待一段时间,而是在发完 ACK 报文段后立即释放连接,那么就无法收到 B 重传的 FIN + ACK 报文段,因而也不会再发送一次确认报文段。 这样,B 就无法安装正常步骤进入 CLOSED 状态

防止前面提到的“已失效的连接请求报文段”出现在本连接中。 A 在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。 这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段

B 只要收到 A 发出的确认,就进入 CLOSED 状态。 同样,B 在撤销相应的传输控制 TCB 后,就结束了这次的 TCP 连接。 B 结束 TCP 连接的时间要比 A 早一些

保活计时器(keepalive timer):服务器每收到一次客户的数据,就重新设置保活计时器,时间的设置通常是两小时。 若两小时没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔75秒发送一次。 若一连发送10个探测报文段后仍无客户的响应,服务器就认为客户端出了故障,接着就关闭这个连接

TCP 的有限状态机

为了更清晰地看出 TCP 连接的各种状态之间的关系,下图为 TCP 的有限状态机。 图中每一个方框即 TCP 可能具有的状态。 每个方框中的大写英文字符串是 TCP 标准所使用的 TCP 连接状态名。 状态之间的箭头表示可能发生的状态变迁。 箭头旁边的字,表明引起这种变迁的原因,或表明发生状态变迁后又出现什么动作。 请注意图中有三种不同的箭头。 表示对。 表示对。 另一种表示粗实线箭头客户进程的正常变迁粗虚线箭头服务器进程的正常变迁细线箭头异常变迁

参考:TCP协议详解 - 知乎 (zhihu.com)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/673831
推荐阅读
相关标签
  

闽ICP备14008679号