从TCP首部来看TCP协议

从TCP首部来看TCP协议

本篇文章从TCP首部的内容发散出TCP协议涉及到的各个细节,可以更好的理解TCP协议

TCP首部

首先展示TCP首部的具体结构和各个字段
从TCP首部来看TCP协议

源端口和目的端口

每个T C P包都包含源端和目的端的端口号,用于寻找发端和收端应用进程。这两个值加
上I P首部中的源端I P地址和目的端I P地址唯一确定一个T C P连接。也就是说,包含客户端IP地址、客户端端口号、服务器 IP地址和服务器端口号的四元组唯一确定一个TCP连接

***

序号用来标识从TCP发端向TCP收端发送的数据字节流,它表示在这个报文段中的的第一
个数据字节。如果将字节流看作在两个应用程序间的单向流动,则TCP用序号对每个字节进
行计数。序号是32 bit的无符号数,序号到达2^32-1后又从0开始。

初始***(ISN)

当一端为建立连接而发送它的 SYN时,它为连接选择一个初始序号。 ISN随时间而变化,因此每个连接都将具有不同的 ISN(比如ISN可看作是一个 2比特的计数器,每4 ms加1)。这样选择序号的目的在于防止在网络中被延迟的分组在以后又被传送,而导致某个连接的一方对它作错误的解释。

确认序号

既然每个传输的字节都被计数,确认序号包含发送确认的一端所期望收到的下一个序号。因此,确认序号应当是上次已成功收到数据字节序号加 1。只有ACK标志(下面介绍)为1时确认序号字段才有效。

首部长度

首部长度给出首部中32 bit字的数目(也就是数这个长度的单位是4字节)。需要这个值是因为选项字段的长度是可变的。这个字段占4 bit,因此TCP最多有60字节的首部。然而,没有任选字段,正常的长度是20字节(那么这4bit存的应该是5)。

6个标志位

在TCP首部中有6个标志比特。它们中的多个可同时被设置为 1。
URG 紧急指针(u rgent pointer)有效(见2 0 . 8节)。
ACK 确认序号有效。
PSH 接收方应该尽快将这个报文段交给应用层。
RST 重建连接。
SYN 同步序号用来发起一个连接。这个标志和下一个标志将在第 1 8章介绍。
FIN 发端完成发送任务。

SYN

SYN标志用来表示一个SYN报文,这个报文用来发起建立连接的请求。接下来就是经典的TCP建立连接的三次握手过程:

  1. 请求端(通常称为客户,客户端)发送一个SYN报文指明客户打算连接的服务器的端口,以及初始***(ISN,在这个例子中为J)。
  2. 服务器发回包含服务器的初始序号的SYN报文作为应答。同时,将确认***设置为客户的ISN加1以对客户的SYN报文段进行确认。一个SYN报文将占用一个序号。
  3. 客户必须将确认序号设置为服务器的 ISN加1以对服务器的SYN报文段进行确认。从TCP首部来看TCP协议

FIN

建立一个连接需要三次握手,而终止一个连接要经过 4次挥手。这是由TCP的半关闭(half-close)造成的。既然一个TCP连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭。
首先进行关闭的一方(即发送第一个 FIN)将执行主动关闭,而另一方(收到这个 FIN)执行被动关闭。通常一方完成主动关闭而另一方完成被动关闭。四次挥手的过程如下:
从TCP首部来看TCP协议
在这期间的确认号和***的规则和握手是一样的,和SYN报文一样,FIN报文也占用一个***

关于read返回0

我们在进行网络编程的时候,通常判断read返回0来判断对端关闭,这是因为在tcp中,通信的某一段在收到FIN报文后,TCP服务会向上层应用程序传送一个文件结束符,通过这个文件结束符就能通知应用程序对端关闭了。

窗口大小

TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个 16 bit字段,因而窗口大小最大为65535字节。允许这个值按比例变化以提供更大的窗口。

检验和

检验和覆盖了整个的TCP报文段:TCP首部和TCP数据。这是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证。

紧急指针

只有当URG标志置1时紧急指针才有效。紧急指针是一个正的偏移量,和***的值相加表示紧急数据最后一个字节的序号。 TCP的紧急方式是发送端向另一端发送紧急数据的一种方式,注意这个紧急数据是嵌在普通数据里的。TCP只通过紧急指针这个偏移量指示紧急数据的最后一个字节的位置,因此没有办法确认紧急数据的开始位置,需要应用层想办法解决。

选项

最常见的可选字段是最长报文长度,又称为 MSS (Maximum Segment Size)。每个连接方通常都在通信的第一个报文段(为建立连接而设置 S Y N标志的那个段)中指明这个选项。它指明本端所能接收的最大长度的报文段。

最大报文长度(MSS)

最大报文段长度(MSS)表示T C P传往另一端的最大块数据的长度(不包括TCP首部的长度)。当一个连接建立时,连接的双方都要通告各自的 MSS。

注意:MSS不包含TCP报文的首部,说的是数据的长度

在有些书中,将它看作可“协商”选项。它并不是任何条件下都可协商。当建立一个连接时,每一方都有用于通告它期望接收的 MSS选项(MSS选项只能出现在SYN报文段中)。如果一方不接收来自另一方的 MSS值,则MSS就定为默认值536字节。

再谈最大传输单元(MTU)

最大传输单元虽然不是TCP首部的选项的内容,但是我们经常讲MTU与MSS混在一起。首先要搞清楚的是,MSS是TCP中的概念,是传输层的概念而MTU是链路层的概念。在链路层中,不同协议对传输的数据帧(通常称在链路层传输的数据为帧,在传输层的数据为段)的长度都有一个限制,比如以太网和802.3对数据帧的长度都有一个限制,其最大值分别是1500和1492字节。链路层的这个特性称作MTU,最大传输单元。

注意:MTU描述的是链路层的可传输数据的大小,因此不包括链路层的首部。当然这个数据肯定是经由TCP(或UDP等),IP封装的,因此包括了传输层和网络层的头部长度

分段和分片

谈到MSS和MTU,不得不讲的就是分段和分片的概念了。

分段

既然传输层有最大报文长度,而TCP是面向字节流的传输协议,数据之间没有界限,那么当要发送的数据大于MSS了,怎么办,这个时候就需要进行分段了,将数据段分成满足MSS的数据段的大小再进行发送。

分片

分段分好以后,一个TCP数据段的大小就满足MSS了,数据此时加上TCP首部就被发送到网络层了,网络层加上IP首部以后又要考虑一个事情了——链路层有MTU的限制。所以IP报文的大小又要满足小于等于MTU,因此需要进行分片,把数据分层若干片,每一片的大小都小于MTU。由于不同链路段的MTU不同,分片可以发生在原始发送端主机上,也可以发生在中间路由器上

把一份IP数据报分片以后,只有到达目的地才进行重新组装(这里的重新组装与其他网络协议不同,它们要求在下一站就进行进行重新组装,而不是在最终的目的地)。重新组装由目的端的 I P层来完成,其目的是使分片和重新组装过程对运输层( T C P和U D P)是透明的。

尽管I P分片过程看起来是透明的,但有一点让人不想使用它:即使只丢失一片数据也要重传整个数据报。为什么会发生这种情况呢?因为 IP层本身没有超时重传的机制——由更高层来负责超时和重传(TCP有超时和重传机制,但UDP没有。一些UDP应用程序本身也执行超时和重传)。当来自TCP报文段的某一片丢失后,**TCP在超时后会重发整个TCP报文段,没有办法只重传数据报中的一个数据报片。**事实上,如果对数据报分片的是中间路由器,而不是起始端系统,那么起始端系统就无法知道数据报是如何被分片的,显然无法重发某个特定片。因此,经常要避免分片

使用UDP很容易导致I P分片,因为UDP是面向数据报的传输协议,数据报之间有固定的界限,在不考虑丢包的情况下,发送端发送了几次,接收端就需要接收几次。所以数据报的长度经常会超过MTU,从而导致分片。

TCP协议试图避免分片,TCP由于有MSS的存在,因此TCP一般将MSS设置为小于MTU减去TCP首部长度和IP首部长度的大小来避免分片。

数据

到TCP报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。

参考文献

TCP-IP详解卷一