章节六:面向连接的传输:TCP

在上一章可靠数据传输原理了解了TCP可靠数据传输的原理,接下来来了解TCP的一些相关的内容,包括TCP的工作流程、TCP报文段结构、流量控制及拥塞控制。首先我们从TCP的工作流程来入手。

1 TCP连接

TCP是面向连接的,提供全双功的服务协议。所谓面向连接,是指在通信的双方主机上维护这个当前连接的一些状态,如序列号、确认号等信息。同时TCP就是通过维护这些状态变量从而实现了可靠数据传输的,在3.4可靠数据传输原理的深入学习我们就可以了解,是因为什么从而引入这些变量的。所谓全双工是指,交互的主机双方,既可以是发送方,又可以是发送方,数据是在交互方双向流动的。

接下来我们再来讨论下TCP数据传输的流程,在之前我们先来了解一下最大报文段长度(Max Segment Size,MSS)和最大传输单元(Max Transmission Unit,MTU)。MTU是指发送主机链路层能发送最大帧的长度。一般来说MTU的值为1500字节。在网络层,其首部长度为20字节,TCP的首部一般为20字节(TCP首部长度是可变的),那么1500-40=1460,所以一般通过TCP并通过网络层传输数据的话,那么有效荷载最大为1460字节。那么这个最大有效荷载就是MSS,MSSS是指一个报文段最大可搭载的数据长度,而不包括TCP首部。

当TCP建立连接后,会相应的在发送端和接收端建立发送缓存和接收缓存。在发送端上层调用发送数据交付给TCP后,数据就由TCP控制,TCP会将数据放入发送缓存,TCP从发送缓存中获取数据发送。在接收端,TCP接收到数据后将数据放入接收端缓存,上层的应用程序从缓存中获取数据。其流程如下:
在这里插入图片描述

2 TCP报文段结构

接下来来看下TCP报文端的结构,如下:
在这里插入图片描述如上图为TCP报文段的结构,前32比特位分别为源端口号和目的端口号,紧接的两个32比特位位序列号和确认号。紧接后续的4比特未首部长度,正常来说4比特能标识最大值为15,那么如何首部长度呢?这里的首部长度是指的以32比特字为单位的个数,也就是图中的一行。那么这个就可以标识的长度很长了。紧接着是保留的4比特的保留字段。紧接着是8个比特位的状态位,各不相同。其后16比特是接收窗口,用于流量控制。检验和用于对数据进行差错校验。以及之后的紧急数据指针,到此为固定的20字节TCP首部,紧接下来就是选项参数,这个是可变的,所以才会有首部长度这个字段。完了之后紧接着就是真正的数据了。这些字段的含义在后续的内容会涉及到其具体的应用。

2.1 序列号和确认号

接下来来讨论一下TCP报文段中序列号和确认号。在3.4章节会有一个序号范围为每个分组编号,用于作为该分组的唯一标识,TCP使用同样的原理,但是与3.4讨论不同的是TCP的序列号是当前分组的第一个字节在整个数据中的字节序号,TCP将数据看成一个顺序的流并为每个字节编号,那么在发送时,发送的这个分组的第一个字节作为其序列号。假如发送方要发送5000字节的数据,而MSS为1000字节,那么第一个报文段的序号为0,第二个报文段的序号为1000,第三个报文段的序号为2000,以此类推,如下图:
在这里插入图片描述
那么确认号是什么呢?确认号是代表接收方期望下一个收到分组的序列号。假如主机A接收到主机B的一个字节序号为0-499的分组,那么主机A需要等待主机B的序号为500及之后分组,同时主机A需要向主机B发送数据,所以此时主机A发送主机B的数据就会带上确认号501。那么如果主机A收到来自主机B的0-499和1000-1499的分组,那么此时主机A会接收两个分组并缓存,同时在主机A向主机B发送数据时会带上确认号为500的数据,来表示主机A想收到主机B的序号为500的分组数据。为了说明序列号和确认号,看下图,主机A接收用户的输入,然后将用户输入的字符’C’传输至主机B,主机接收到数据后,然后将数据显示并传回主机A然后显示:
在这里插入图片描述

3 TCP连接管理

前面我们提到过,TCP提供面向连接的可靠数据传输就是在发送方和接收方维护一些变量从而维持数据可靠传输,同时在传输数据之前进行我们熟知的三次握手,从而达到可靠数据传输的目的,那么三次握手是如何实现的呢?假设在客户应用程序想和服务器应用程序进行交互,那么客户主机请求TCP进行数据传输,那么TCP会首先进行三次握手。

3.1 TCP的三次握手

  1. 客户端的TCP会向服务端发送一个特殊的TCP报文段。该报文段的SYN比特位被置为1,同时客户端初始化一个随机序列还client_isn,将该序列号放入序列号字段中,当然该特殊的报文段是不能够携带数据的,该报文段被称之为SYN报文段。
  2. 服务端在收到客户端的SYN报文段后,为该客户端的连接分配变量和缓存,同时组装一个特殊的报文段,同样是将SYN比特位置为1,同时初始化一个服务端随机序列号server_isn,同时键client_isn+1作为确认号放入确认号字段中,然后将该特殊的报文段传输给客户端。这个特殊的报文段称之为SYNACK报文段。
  3. 客户端再收到服务端的SYNACK报文段后,为该连接分配变量和缓存,同时组织TCP报文段,将client_isn+1作为序列号,同时将server_isn作为确认号放入确认号字段,当然此时的SYN比特位被置为0,因为客户端和服务端的连接已经建立,同时该报文段也可以携带数据。

TCP的三次握手的流程如下:
在这里插入图片描述

3.2 TCP的四次挥手

在了解了TCP连接时的三次握手,接下来我们来看看TCP的断开连接时的四次挥手的流程,如下图:
在这里插入图片描述
如图所示,在客户端发起断开连接时(当然服务端也可以发起),首先客户端发送一个FIN比特被置为1的报文段,当服务端接收到报文段后,发送一个ACK,这里客户端发起关闭连接时因为客户端知道自己没数据可以发送了,所以会发起关闭请求,当时此时服务端可能还在发送数据,所以此时客户端还是可以接收数据的,当服务端确认没有需要发送的数据,那么服务端同样发送一个FIN比特位被置为1的报文段,当客户端接收到该报文段后,发送一个ACK。此时两台主机维护的变量和缓存均被释放了。

在整个从创建连接到关闭连接,客户端和服务端均会有多个状态的改变,下图为客户端和服务端的状态转变:

客户端状态转变:
在这里插入图片描述
服务端状态转变:
在这里插入图片描述

3.3 连接时操作系统内核是如何工作的

在了解了TCP的三次握手和四次挥手的状态转变后,我们来看一下在连接时,系统内核是如何工作的,如下图:
在这里插入图片描述

4 流量控制

我们之前可能听说过流量控制和拥塞控制,那么这两个区别是什么呢?首先来说一下流量控制,在3.5开始时我们了解到TCP的发送方和接收方都会分配缓存,在接收方将接收到数据放入缓存中,然后上层应用从缓存中读取数据,但是我们知道接收方不可能咋实时的读取数,那么就会导致由于发送方发送数据过多,而接收方的上层应用来不及读取缓存中的数据,从而导致缓存溢出,数据丢失。那么为了控制发送方和接收方的速率达到一致,保证缓存不会溢出,从而引入流量的控制。拥塞控制是用来处理网络的原因的。后续会讨论。
TCP的流量控制是通过在发送方维护一个接收窗口而实现的。接收窗口指示发送数据的一方接收方的缓存空间还有多少,发送方还可以发送多少数据。当然接收窗口的值是动态的。接收窗口初始时就等于接收方分配的缓存发小为RcvBuffer。这里先定义两个变量:

LastByteRead:	接收方应用程序从缓存中读取的数据流中最后一个字节编号。
LastByteRcvd:	从网络中到达并且放入接收方缓存中的数据流的最后一个字节编号。

由于TCP不允许分配的缓存溢出,那么下面的公式必须成立:

LastByteRcvd - LastByteRead <= RcvBuffer

那么接收窗口rwnd可以用以下表示:

rwnd = RcvBuffer - [LastByteRcvd  - LastByteRead ]

也就是说接收方每次向发送方发送ACK确认数据时,会在接收窗口这个字段将每次可以接收数据大小放入。那么发送方是如何处理的呢?在发送方会监控两个状态:

LastByteSend:	发送方已经发送数据的最后一个字节编号。
LastByteAcked:	发送方已发送当未确认的最小字节编号。

那么LastByteSend - LastByteAcked就是发送端发送到接收端并且为接收的数据。所以在接收方保证以下条件满足即可:

LastByteSend - LastByteAcked <= rwnd

这样就实现了流量的控制。当然这里会有个问题,假设主机A和主机B进行交互,当主机B向主机发送接收窗口为0,同时主机B不再向主机A发送数据,那么主机A在收到主机B的接收窗口为0,那么主机A则不再发送数据,等待主机B的接收窗口大于0,但是主机B不再发送数据,那么主机A会一直等待,即使主机B已经清除缓存中的数据。很明显这种方法容易导致主机A和主机B互相等待。TCP是如何解决的呢?TCP的发送方在接收到接收端的接收窗口为0时,仍然发送一个数据长度为1字节的数据,那么在接收端,当缓冲区清空后,会对发送端发送的1字节数进行确认,那么发送端又可以获得接收端实时的接收窗口,然后继续发送数据。

下一节来了解TCP的拥塞控制原理:TCP拥塞控制原理

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值