理解 TCP(二):报文结构

更好阅读体验:《理解 TCP 和 UDP》— By Gitbook

TCP 是面向字节流的,但传送的数据单元却是报文段。

什么是报文?
例如一个 100kb 的 HTML 文档需要传送到另外一台计算机,并不会整个文档直接传送过去,可能会切割成几个部分,比如四个分别为 25kb 的数据段。
而每个数据段再加上一个 TCP 首部,就组成了 TCP 报文。
一共四个 TCP 报文,发送到另外一个端。
另外一端收到数据包,然后再剔除 TCP 首部,组装起来。
等到四个数据包都收到了,就能还原出来一个完整的 HTML 文档了。

在 OSI 的七层协议中,第二层(数据链路层)的数据叫「Frame」,第三层(网络层)上的数据叫「Packet」,第四层(传输层)的数据叫「Segment」。

TCP 报文 (Segment),包括首部和数据部分。

报文结构.png

而 TCP 的全部功能都体现在它首部中各字段的作用,只有弄清 TCP 首部各字段的作用才能掌握 TCP 的工作原理。
TCP 报文段首部的前20个字节是固定的,后面有 4N 字节是根据需要而增加的。
下图是把 TCP 报文中的首部放大来看。

报文首部结构.png

TCP 的首部包括以下内容:

  1. 源端口 source port

  2. 目的端口 destination port

  3. 序号 sequence number

  4. 确认号 acknowledgment number

  5. 数据偏移 offset

  6. 保留 reserved

  7. 标志位 tcp flags

  8. 窗口大小 window size

  9. 检验和 checksum

  10. 紧急指针 urgent pointer

  11. 选项 tcp options

下面展开来描述个字段的意义和作用。

TCP 首部各字段的意义和作用

源端口和目的端口 Port

各占 2 个 字节,共 4 个字节。
用来告知主机该报文段是来自哪里以及传送给哪个应用程序(应用程序绑定了端口)的。
进行 TCP 通讯时,客户端通常使用系统自动选择的临时端口号,而服务器则使用知名服务端口号。

序号 Sequence Number

占 4 个字节。
TCP 是面向字节流的,在一个 TCP 连接中传输的字节流中的每个字节都按照顺序编号。
例如 100 kb 的 HTML 文档数据,一共 102400 (100 * 1024) 个字节,那么每一个字节就都有了编号,整个文档的编号的范围是 0 ~ 102399。

序号字段值指的是本报文段所发送的数据的第一个字节的序号。
那么 100 的 HTML 文档分割成四个等分之后,
第一个 TCP 报文段包含的是第一个 25kb 的数据,0 ~ 25599 字节, 该报文的序号的值就是:0
第二个 TCP 报文段包含的是第二个 25kb 的数据,25600 ~ 51199 字节,该报文的序号的值就是:25600
......

根据 8 位 = 1 字节,那么 4 个字节可以表示的数值范围:[0, 2^32],一共 2^32 (4294967296) 个序号。
序号增加到最大值的时候,下一个序号又回到了 0.
也就是说 TCP 协议可对 4GB 的数据进行编号,在一般情况下可保证当序号重复使用时,旧序号的数据早已经通过网络到达终点或者丢失了。

确认号 Acknowledgemt Number

占 4 个字节。
表示期望收到对方下一个报文段的序号值
TCP 的可靠性,是建立在「每一个数据报文都需要确认收到」的基础之上的。
就是说,通讯的任何一方在收到对方的一个报文之后,都要发送一个相对应的「确认报文」,来表达确认收到。
那么,确认报文,就会包含确认号
例如,通讯的一方收到了第一个 25kb 的报文,该报文的 序号值=0,那么就需要回复一个确认报文,其中的确认号 = 25600.

数据偏移 Offset

占 0.5 个字节 (4 位)。
这个字段实际上是指出了 TCP 报文段的首部长度 ,它指出了 TCP报文段的数据起始处 距离 TCP报文的起始处 有多远。(注意 数据起始处 和 报文起始处 的意思)

一个数据偏移量 = 4 byte,由于 4 位二进制数能表示的最大十进制数字是 15,因此数据偏移的最大值是 60 byte,这也侧面限制了 TCP 首部的最大长度。

保留 Reserved

占 0.75 个字节 (6 位)。
保留为今后使用,但目前应置为 0。

标志位 TCP Flags

标志位,一共有 6 个,分别占 1 位,共 6 位 。
每一位的值只有 0 和 1,分别表达不同意思。

紧急 URG (Urgent)

当 URG = 1 的时候,表示紧急指针(Urgent Pointer)有效。
它告诉系统此报文段中有紧急数据,应尽快传送,而不要按原来的排队顺序来传送。
URG 要与首部中的 紧急指针 字段配合使用。

确认 ACK (Acknowlegemt)

当 ACK = 1 的时候,确认号(Acknowledgemt Number)有效。
一般称携带 ACK 标志的 TCP 报文段为「确认报文段」。
TCP 规定,在连接建立后所有传送的报文段都必须把 ACK 设置为 1。

推送 PSH (Push)

当 PSH = 1 的时候,表示该报文段高优先级,接收方 TCP 应该尽快推送给接收应用程序,而不用等到整个 TCP 缓存都填满了后再交付。

复位 RST (Reset)

当 RST = 1 的时候,表示 TCP 连接中出现严重错误,需要释放并重新建立连接。
一般称携带 RST 标志的 TCP 报文段为「复位报文段」。

同步 SYN (SYNchronization)

当 SYN = 1 的时候,表明这是一个请求连接报文段。
一般称携带 SYN 标志的 TCP 报文段为「同步报文段」。
在 TCP 三次握手中的第一个报文就是同步报文段,在连接建立时用来同步序号。
对方若同意建立连接,则应在响应的报文段中使 SYN = 1 和 ACK = 1。

终止 FIN (Finis)

当 FIN = 1 时,表示此报文段的发送方的数据已经发送完毕,并要求释放 TCP 连接。
一般称携带 FIN 的报文段为「结束报文段」。
在 TCP 四次挥手释放连接的时候,就会用到该标志。

窗口大小 Window Size

占 2 字节。
该字段明确指出了现在允许对方发送的数据量,它告诉对方本端的 TCP 接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度。
窗口大小的值是指,从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量。
例如,假如确认号是 701 ,窗口字段是 1000。这就表明,从 701 号算起,发送此报文段的一方还有接收 1000 (字节序号是 701 ~ 1700) 个字节的数据的接收缓存空间。

校验和 TCP Checksum

占 2 个字节。
由发送端填充,接收端对 TCP 报文段执行 CRC 算法,以检验 TCP 报文段在传输过程中是否损坏,如果损坏这丢弃。
检验范围包括首部和数据两部分,这也是 TCP 可靠传输的一个重要保障。

紧急指针 Urgent Pointer

占 2 个字节。
仅在 URG = 1 时才有意义,它指出本报文段中的紧急数据的字节数。
当 URG = 1 时,发送方 TCP 就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍是普通数据。
因此,紧急指针指出了紧急数据的末尾在报文段中的位置。

参考

《后台开发 核心技术与应用实践》
《计算机网络》


搬砖码农
Call me JerryC

Peace of mind, Code of enjoy

3.5k 声望
1.1k 粉丝
0 条评论
推荐阅读
ServiceWorker 缓存与 HTTP 缓存
虽然 ServiceWorker 和 PWA 正在成为现代 Web 应用程序的标准,但浏览器资源缓存变得比以往任何时候都复杂。 本文涵盖了浏览器缓存的重点内容,具体包括:

JerryC2阅读 1.6k

化虹为桥 - Nginx 如何代理 UDP “连接”
众所周知,UDP 并不像 TCP 那样是基于连接的。但有些时候,我们需要往一个固定的地址发送多个 UDP 来完成一个 UDP 请求。为了保证服务端能够知道这几个 UDP 包构成同一个会话,我们需要在发送 UDP 包时绑定某个端...

spacewander4阅读 1.1k

Qt中使用TCP接收报文
假设有一个TCP服务端,会向连接到它的TCP客户端周期(或随机)发送一个报文。报文由定长的报文头和不定长的报文体(数据部分)组成,报文体是一张图片,每个字节表示图片中一个像素的灰度值。我们的任务就是读取...

manxisuo阅读 664

Envoy/Istio 连接生命周期与临界异常 —— 不知所谓的连接 REST
本文目标:说明 Envoy 连接控制相关参数作用。以及在临界异常情况下的细节逻辑。目标是如何减少连接异常而引起的服务访问失败,提高服务成功率。

MarkZhu阅读 250

传输层之UDP与TCP的首部
传输层位于应用层和数据链路层之间,主要有两个协议,用户数据报协议UDP(User Datagram Protocol)、传输控制协议TCP(Transmission Control Protocol)。

一颗冰淇淋阅读 238

高性能网络SIG月度动态:virtio新设备进入virtio规范、smc新特性IPC性能比tcp提升88% | 龙蜥SIG
高性能网络 SIG :在云计算时代,软硬件高速发展,云原生、微服务等新的应用形态兴起,让更多的数据在进程之间流动,而网络则成为了这些数据流的载体,在整个云时代扮演者前所未有的重要角色。在这个万物互联的时...

龙蜥社区阅读 237

封面图
TCP四次挥手会经历这么多状态
TCP三次握手 中讲述了序列号和建立连接,这一篇来说说释放连接。标志位TCP首部中在属性标志位,和建立连接、释放连接有关,位于保留和窗口字段中间,其中三个标识与断开连接有关。ACK: acknowledgment(确认)---...

一颗冰淇淋阅读 219

Peace of mind, Code of enjoy

3.5k 声望
1.1k 粉丝
宣传栏