2.3面向连接的传输——TCP协议

TCP概述

TCP是面向连接的,因为进行数据传输前需要进行“三次握手

TCP连接提供的是全双工服务, 即应用层数据可以从进程B流向进程A,也可以从进程A流向进程B

TCP连接是点对点的,即咋单个发送方与单个接收方之间的连接。

一个简单的TCP流程如下图所示:

可以看出,TCP连接的组成包括:一台主机上的缓存、变量和与进程连接的套接字,以及另一台主机上的另一组缓存、变量和与进程连接的套接字。 

TCP报文段

下图为一个TCP报文段结构:

报文段由首部字段和一个数据字段组成。数据字段包含一块应用数据(最大长度被最大报文段长度(MSS)限制,MSS即TCP可从缓存中取出并放入报文段中的数据数量)

源端口号和目的端口号:用于多路复用/分解来自或送到上层应用的数据

序号和确认号字段:均为32比特,被TCP发送方和接收方用来实现可靠数据传输服务。

首部长度字段: 4比特,知识了以32比特的字为单位的TCP首部长度。

标志字段:6比特,ACK比特用于指示字段中的值是有效的。RST、SYN、FIN比特用于连接建立和拆除。当PSH字段被设置时,就只是接收方应立即将数据交给上层。URG比特用来指示报文段里存在着被发送端上层实体置为“紧急”的数据。紧急数据的最后一个字节由16比特的紧急数据指针字段指出。

接收窗口字段:用于流量控制,即知识接收方愿意接受的字节数量。

检验和字段:用于进行差错检测

选项字段:用于发送方与接收方协商最大报文段长度(MSS)时,或在高速网络环境下用作窗口调节因子时使用。

对于序号和确认号:

一个报文段的序号是该报文段首字节的字节流编号。 一个报文段的确认号是该主机期望从连接主机收到的下一字节的序号。

下图为学习序号和确认号的一个例子:假设客户和服务器其实序号为42和79

开始时主机A即客户端向服务器端主机B发送报文序号为42,由于没有接受到服务器的任何数据,故确认号为79。第二个报文段是服务器B向主机A发送,序号为79,并且确认号为43,告诉主机A已经收到42号以及之前的报文,期望收到43号报文。第三段为主机A发送序号为43的报文,并期望收到80号报文。

往返时间的估计与超时

TCP和之前的rdt协议一样,采用超时/重传机制来处理报文段的丢失。那么和之前的问题一样,超时间隔长度如何设置。显然,超时间隔必须大于该链接的往返时间(RTT),即一个报文段发出到它被确认的时间,否则会造成不必要的重传。

估计往返时间

TCP根据公式来进行往返时间的估计。

其中,SampleRTT为从某报文段被发出(即交给IP)到对该报文段的确认被收到之间的时间量。注意大多数TCP尽在某个时刻做一次SampleRTT,另外绝不为已被重传的报文段计算SampleRTT。

EstimatedRTT为对SampleRTT的平均结果。每次获得一个新的SampleRTT就会 通过上式更新EstimatedRTT。

在[RFC 6298]中给出的α的参考值为0.125  故,上式变为

 除了估算RTT外,测量RTT的变化也是有价值的。定义DevRTT用于,估算SampleRTT一般会偏离EstimatedRTT的程度:

通常β取0.25。 

设置和管理时间间隔

 假设给出了EstimatedRTT和DevRTT,考虑到时间间隔过小,会造成不必要的重传。超过的时间间隔也不能过大否则TCP不能很快重传该报文,导致数据传输时延大。故时间间隔

推荐初始TimeoutInterval为1秒。 

可靠数据传输

之前已经了解到,TCP在IP不可靠的尽力而为的服务之上创建了一种可靠数据传输服务。TCP可靠数据传输服务确保了一个进程从其接收缓存中读出的数据流是无损坏、无间隔、非冗余和按时序的数据流。

但是和之前所说的每个已发送但未被确认的报文段都与一个定时器相关联不同的是TCP使用单一的重传定时器,因为定时器的管理需要相当大的开销。

简化的TCP发送方有3个与发送和重传有关的主要事件:

  • 1.从上层接收数据:TCP从应用程序接收数据,将数据封装在一个报文段中,并把该报文段交给IP。如果定时器还没有为某些其他报文段运行,则当报文段传给IP时,TCP就启动该定时器。间隔为TimeoutInterval。
  • 2.定时器超时:TCP通过重传引起超时的报文段来响应超时事件。然后TCP重启定时器
  • 3.收到ACK:TCP将ACK的值y与它的变量SendBase进行比较。SendBase是最早未被确认的字节的序号。如前面指出,TCP采用累积确认,所以y确认了字节编号在y之前的所有字节都已经收到。如果y大于SendBase,则该ACK是在确认一个或锁哥先前未被确认的报文段。因此发送方更行它的SendBase变量。如果当前有未被确认的报文段,TCP还要重新启动定时器。

实际TCP在实现中对上文简化的TCP所作的修改

超时间隔加倍 :每当超时事件发生时每次TCP重传会将下一次的超时间隔设置为之前的两倍。这种修改提供了一个形式受限的拥塞机制。对于另外两个时间即受到上层应用数据和收到ACK则TimeoutInterval仍由最近的EstimatedRTT与DevRTT推算得到

快速重传  :超时出发重传问题之一就是超时周期可能相对较长,从而增加了端到端的时延。因而发送方通常可在超时时间发生之前通过注意所谓冗余ACK来较好地检测丢包。(冗余ACK就是再次确认某个报文段的ACK,而发送方先前已经收到对该报文段的确认。)如果TCP发送方接收到对相同数据的3个冗余ACK,他就会执行快速重传

下图为接收方事件和产生ACK的情况

差错恢复机制:虽然在TCP发送方中仅需保持已发送过但未被确认的字节的最小序号和下一个要发送的字节的序号,但是TCP会正确接收已失序的分组并缓存。因此我们可以认为TCP的差错恢复机制是GBN协议与SR协议的混合体。

流量控制

TCP连接每一侧主机都为该连接设置了接收缓存。如果发送方发送数据较快或者接收方应用数据读取数据时相对缓慢,则发送的数据就会很容易地是该连接的接收缓存溢出。

TCP为它的应用程序提供了流量控制服务,以消除发送方使接收方缓存溢出的可能性。流量控制因此是一个速度匹配服务,即发送方的发送速率与接收方应用程序的读取速率相匹配。

TCP发送方和接收方都维护了一个接收窗口变量来提供流量控制。简单的说接收窗口用于给发送方一个指示——该接收方还有多少可用的缓存空间。如下图所示:

主机B通过把当前rwnd值放入它发给主机A的报文段接收窗口字段中,通知主机A它在该连接的缓存中还有多少可用空间。主机A轮流跟踪两个变量LastByteSent和LastByteAcked,这两个变量差就是主机A发送到连接中但未被确认的数据量。通过将其控制在rwnd内,就不会使主机B的接收缓存溢出。

注意,如果B的接收缓存已满,即rwnd=0.再讲rwnd=0告诉主机A后,还要假设主机B没有任何数据要发送给A,此时就会发生如下情况:B上的应用程序将缓存清空,TCP并不向主机A 发送带有rwnd字段的新报文段。这样主机A 就不可能知道主机B的缓存已经有新空间。   TCP规范中要求:当主机B的接收窗口为0时,主机A 继续发送只有一个字节数据的报文段。这些报文段将会被接收方确认。最终缓存将开始清空,并确认报文里将包含一个非0的rwnd值

TCP连接管理 

TCP连接建立:三次握手

  1. 客户端TCP首先向服务器端的TCP发送一个特殊的TCP报文段,该报文段不包含应用层数据,但是首部标志位SYN比特被置为1。另外客户随机地选择(避免某些安全性攻击)一个初始序号(client_isn)放置于该起始的TCP SYN报文段的序号字段中。该报文段被封装在一个IP数据报中,并发送给服务器。
  2. 服务器接收到IP数据报后提取出TCP SYN报文段,为该TCP连接分配TCP缓存和变量,并向该客户TCP发送允许连接报文段。这个允许连接的报文段也不包含应用层数据。但是报文段首部却包含3个重要信息。首先SYN比特被置为1。其次,该TCP报文段首部的确认号字段被置为client_isn+1。最后,服务器选择自己的初始序号(server_isn),并将其放置到TCP报文段首部的序号字段中。该允许连接的报文段有时被称为SYNACK报文段
  3. 在收到SYNACK报文段之后,客户也给该连接分配缓存和变量。客户主机则向服务器发送另外一个报文段对服务器的允许连接的报文段进行了确认(通过将值server_isn+1放置到TCP报文段首部的确认字段中来完成此项工作)。因为连接已经建立了,所以该SYN比特被置为0。同时再第三个阶段可以在报文段负载中携带客户到服务器的数据。

TCP连接关闭

参与一条TCP连接的两个进程中的任何一个都能终止该连接,当连接结束后,主机中的“资源”(缓存和变量)将被释放。

如上图所示,假设客户应用进程发出一个关闭连接命令。

  • 首先客户TCP向服务器进程发送一个特殊的TCP报文段。这个特殊的报文段让其首部的标志位即FIN比特被置为1。
  • 当服务器接收到该报文段后,就向发送方回送一个确认报文段。
  • 然后服务器发送他自己的终止报文段,其FIN比特被置为1。
  • 最后,该客户对这个服务器的终止报文段进行确认。此时,在两台主机上用于该连接的所有资源都被释放了。

猜你喜欢

转载自blog.csdn.net/weixin_39722922/article/details/88370830