Total Pageviews

Tuesday, 1 September 2020

TCP/IP 数据包的封装与解封


在 TCP/IP 网络中,通信双方的交互过程就是对协议的封装与解封装的过程,发送方数据处理的方式是从高层到底层,逐层进行数据封装。接收方数据处理的方式是从底层到高层,逐层进行数据解封装。接收方的每一层只把对该层有意义的数据拿走,或者说每一层只能处理发送方同等层的数据,然后把其余的部分传递给上一层,这就是对等层通信的概念。

数据封装(Data Encapsulation)是指将协议数据单元(PDU)封装在一组协议头和尾中的过程。该过程是在协议数据单元(PDU)中实现的,其中每层的 PDU 一般由本层的协议头、协议尾和数据封装构成。

数据解封装是指对端的同等层对数据包解析的过程,通过解拆获取需要的数据,然后将数据传递到上层处理。

不同的协议层对数据包有不同的称谓:

  • TCP 传给 IP 的数据单元称作 TCP 报文段或简称为 TCP 段(TCP segment);
  • UDP 数据与 TCP 数据基本一致,唯一的不同是 UDP 传给 IP 的信息单元称作 UDP 数据报(UDP datagram),而且 UDP 的首部长为 8 字节;
  • IP 传给网络接口层的数据单元称作 IP 数据报(IP datagram);
  • 在数据链路层传输的数据单元称作帧(Frame );

下面为应用层数据进入 TCP/IP 协议栈时的封装过程(解封装的过程与该过程相反):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
                                    +-----------------+
| Application data|
+-----------------+
| |
v v
+--------------------------------+
|TCP/UDP header| Application data|
+--------------------------------+
| |
+<-- TCP segment/UDP datagram -->+
v v
+------------------------------------------+
|IP header|TCP/UDP header| Application data|
+------------------------------------------+
| |
+<-------------- IP datagram ------------->+
v v
+--------------------------------------------------------------+
|Eth header|IP header|TCP/UDP header| Application data|Eth tail|
+--------------------------------------------------------------+
| |
<-------------------- Ethernet frame --------------->+
| |
| <----------- 40~1500 Bytes ------------> |

以太网数据帧封装

以太网数据帧(也叫 MAC 帧)是网络硬件上面传送数据的最小单位,它承载了上层(网络层)的通信数据,是网络接口层的封包格式。我们一般接触比较多的是网络接口,比如 eht0、eht1…,这些网络接口上处理的主要数据包就是以太网数据帧。以太网数据帧封装格式在 RFC 894 中定义,具体格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

+----------+---------+------+-----------------------------------+------+
| MAC dst | Mac src | Type | Data | CRC |
+----------+---------+-------------------------------------------------+
6 6 2 | 46~1500 Bytes | 4


| Type |
+------------------------------------------+
|0x800 | IP datagram |
+------+-----------------------------------+
2 46~1500 Bytes

| Type |
+-------------------------+
|0x806 | ARP |PAD|
+------+------------------+
2 28 18

| Type |
+-------------------------+
|0x8035| RARP |PAD|
+-------------------------+
2 28 18

IP 数据报封装

IP 协议处于网络层,几乎所有上层协议都会使用到 IP 协议。 IP 有两种版本,一种是目前使用最广泛的 IPv4 (Internet Protocol version 4, 因特网协定第四版), 一种则是预期未来会热门的 IPv6 。
IPv4 记录的地址长度为 32 bit(4 Bytes),IPv6 的地址可以达到 128 bit(16 Bytes)。
下面为 IP 数据报的封装格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| 4 bits  | 4 bits  |    8 bitys     |3bits|          13 bits             |
+-------------------------------------------------------------------------+
| Version | IHL |Type of Service | Total Length |
+---------+---------------------------------------------------------------+
| Identification |Flags| Fragmentation Offset |
+-------------------+-----------------------------------------------------+
| Time To Live | Protocol | Header Checksum |
+-------------------+----------------+------------------------------------+
| Source Address |
+-------------------------------------------------------------------------+
| Destination Address |
+-------------------------------------------------------------------------+
| Options(Up to 40 bytes) |
+-------------------------------------------------------------------------+
| |
| Data |
| |
+-------------------------------------------------------------------------+
  • Version(版本): 版本号指定 IP 协议的版本,长度为 4 bits。对于 IPv4 来说,其值为 4;
  • IHL(Internet Header Length, IP 数据报头部长度):IP 数据报的头部长度,不包括数据部分,单位为 4 字节。由于该字段为 4 bits,所以 IP 封包头部最长为 (2^4-1)x4=60 字节;
  • Type of Service(服务类型):服务类型包括一个 3 位的优先权字段(现已被弃用),4 位的 TOS 字段和 1 位保留字段(必须置0)。4 位 TOS 字段分别表示最小延时、最大吞吐量、最高可靠性和最小费用;
  • Total Length(总长度):总长度表示整个 IP 数据报的长度,以字节为单位,可以看出最大值为 2^16-1=65535 字节;
  • Identification(标识码):标示字段唯一的标示主机发送的每一个 IP 数据报,初始值由系统随机生成;
  • Flags: 标志的第一位保留,第二位表示「禁止分片」。如果设置了这个位,系统不对 IP 报文分片。在这种情况下,如果 IP 数据报的长度超过 MTU(Max Transfer Unit,最大传输单元),IP 模块将丢弃该数据报并返回一个 ICMP 差错报文。第三位表示「更多分片」,如果为 1,表示后续还有该 IP 报文的分片;
  • Fragment Offset(分片偏移): 分片偏移是分片相对原始 IP 数据报开始处的偏移,在接收端组合分片时,根据这个字段决定各分片的先后顺序;
  • Time To Live(TTL, 存活时间): 表示这个IP封包的存活时间,范围为0-255。当这个IP封包通过一个路由器时, TTL就会减一,当TTL为0时,这个封包将会被直接丢弃;
  • Protocol(协议代码): 协议字段用来区分上层的协议,其中 ICMP 是 1,TCP 是6,UDP是 17,更多可查看 /etc/protocols 文件;
  • Header Checksum(头部校验码): 头部校验码由发送端填充,接收端使用 CRC 循环冗余校验算法检查 IP 数据报是否损坏;
  • Source Address: 发送端 IP 地址
  • Destination Address: 接收端 IP 地址
  • Options: 选项部分长度最大为 40 字节,最小为 0 字节。因为头部长度字段最大可表示 15,也就是说 IP 数据报的报头最大可以有 60 字节,而前面这些已经占了 20 字节,故选项部分最多只能有 40 字节。

IP 分片

当要发送的数据大于 MTU 的时候,通常需要进行 IP 分片,将数据分成多个 IP 数据报发送。MTU 一般为 1500 字节。

由上文可知,在 3 位的标志字段中,如果允许分片,则相同的 16 位的标识字段标识这些分片属于同一个数据块,片偏移标识这些分片的先后顺序。

IP 相关的概念

IP 地址的组成

IP 地址是一个 32 bits 的数值,为了记忆方便,一般将其写成 4 段以 . 号分隔的十进制形式:

1
2
3
IP的表示式: 
00000000.00000000.00000000.00000000 ==> 0.0.0.0
11111111.11111111.11111111.11111111 ==> 255.255.255.255

一个 IP 地址分为 Net_ID(网络号)和 Host_ID(主机号)两部分:

1
2
3
4
192.168.0.0~192.168.0.255 这个Class C 的说明:
11000000.10101000.00000000.00000000
11000000.10101000.00000000.11111111
|----------Net_ID---------|HOST_ID|

同一网段

在同一个物理网段内,主机的 IP 具有相同的 Net_ID(网络号) ,并且具有唯一的 Host_ID(主机号),那么这些 IP 群就是在同一个网段。

在同一个网段内,Net_ID 是不变的,而 Host_ID 则是不可重复,此外,Host_ID 在二进位的表示法当中,不可同时为 0 也不可同时为 1 ,因为全为 0 表示整个网段的地址(Network IP),而全为 1 则表示为广播的地址(Broadcast IP)。

IP 地址的分类

InterNIC 将整个 IP 网段分为五种等级, 每种等级的范围主要与 IP 那 32 bits 数值的前面几个位有关,基本定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
以二进位说明Network第一个数字的定义: 
Class A : 0 xxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx ==> NetI_D的开头是0
|--net--|---------host------------|
Class B : 10 xxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx ==> NetI_D的开头是10
|------net-------|------host------|
Class C : 110 xxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx ==> NetI_D的开头是110
|-----------net-----------|-host--|
Class D : 1110 xxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx ==> NetI_D的开头是1110
Class E : 1111 xxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx ==> NetI_D的开头是1111

五种分级在十进位的表示:
Class A : 0.xx.xx.xx ~ 127.xx.xx.xx
Class B : 128.xx.xx.xx ~ 191.xx.xx.xx
Class C : 192. xx.xx.xx ~ 223.xx.xx.xx
Class D : 224.xx.xx.xx ~ 239.xx.xx.xx
Class E : 240.xx.xx.xx ~ 255.xx.xx.xx

子网划分

前面我们知道了标准的 5 种 IP 等级划分,在一个 A 类网络中最多能有 2^24-2=16777214 台主机。其实在实际应用中一个网络不可能有这么多主机,有这么多主机意味着时时刻刻都会发生广播(比如 ARP 广播)风暴,导致一个网络的主机通信阻塞,根本不能正常工作。

为了解决上述问题,我们可以将一个大网络切分的更细点,让同一个网络中主机的数据量控制在合理的范围。具体的做法就是通过向 IP 的主机位借位,使其成为网络位,这样主机位就缩短了,从而减少了一个网络中主机的数量。

举例:一个 C 类 IP 地址网络位有 24 位,主机位有 8 位,那么这种情况下一个 C 类网络中就最多有 2^8-2=254 台主机。如果我们向主机位借一位,使其成为网络位,那么此时网络位就有 25 bit,主机位有 7 bit,所以此时一个网络中最多有 2^7-2=126 台主机。

子网掩码

子网掩码(Netmask)也是 32 位数值,在数值上,位于 Net_ID(网络位)的为 1,而 Host_ID(主机位)为 0

1
2
3
4
5
6
192.168.0.0~192.168.0.255 这个C Class 的Netmask 说明
第一个IP: 11000000.10101000.00000000.00000000
最后一个: 11000000.10101000.00000000.11111111
|----------Net_ID---------|--host--|
Netmask : 11111111.11111111.11111111.00000000 <== Netmask 二进位
255 . 255 . 255 . 0 <== Netmask十进位

网络相关的几个参数

  • Network:一个网络中的第一个 IP, Host_ID(网络位) 全为 0 时的 IP 地址,此时表示整个网段;
  • Broadcast:一个网络中的最后一个 IP,Host_ID(网络位) 全为 1 时的 IP 地址,即广播地址;
  • Netmask:位于 Net_ID(网络位)的为 1,而 Host_ID(主机位)为 0,此时的 IP 即为子网掩码;
    例题:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    试着计算出 172.16.0.0,但 Net_ID 占用 23 位时,这个网络的 Netmask, 
    Network, Broadcast 等参数?
    ---------------------------------------------------------------------
    解答:
    由于 172.16.xxx.xxx 是在 Class B 的等级当中,亦即 Net_ID 是16 位才
    对。不过题目给的Net_ID 占用了23 个位!等于是向 Host_ID 借了(23-16)
    7 个位用在 Net_ID 当中。所以整个 IP 的位址会变成这样:

    预设: 172 . 16 .0000000 0.00000000
    |----Net_ID-------|--Host--|
    Network: 172.16.0000000 0.00000000 172.16.0.0
    Broadcast: 172.16.0000000 1.11111111 172.16.1.255
    Netmask: 11111111.11111111.1111111 0.00000000 255.255.254.0

CIDR(Classless Interdomain Routing)

一般来说,如果我们知道了 Network 以及 Netmask 之后,就可以定义出该网段的所有 IP 了,因此,我们常常会以 Network 以及 Netmask 来表示一个网段,例如这样的写法:

1
2
3
Network/Netmask
192.168.0.0/255.255.255.0
192.168.0.0/24 <==因为 Net_ID 共有 24 bits

一般我们将一个网段 Network/网络位数量 这种写法称作 CIDR,比如:192.168.0.0/24。

路由概念

在同一个网段中可以通过局域网广播的方式传递数据报,但是在不同的网段中通信就需要借助于路由器的帮忙了。

我们以下面图示的例子来做说明。下列图示当中共有两个不同的网段,分别是Network A 与Network B,这两个网段是经由一部路由器(Server A) 来进行资料转递的,那么当 PC01 这部主机想要传送资料到 PC11 时, 它的IP 封包该如何传输呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
+--------------------------------------------------+
| Network A |
| |
| +-------+ +-------+ |
| | | | | |
| | PC 01 | | PC 02 | |
| | | | | |
| +-------+--------+---------+-------+ |
| IP: 192.168.0.1 | IP: 192.168.0.2 |
| GW:192.168.0.254 | GW:192.168.0.254 |
+--------------------------------------------------+
|
192.168.0.254
+--------+
| |
|Server A|
| |
+--------+
192.168.1.254
|
+--------------------------------------------------+
| | |
| +-------+--------+-----------+-------+ |
| | | | | |
| | PC 11 | | PC 12 | |
| | | | | |
| +-------+ +-------+ |
| IP: 192.168.1.1 IP: 192.168.1.2 |
| GW:192.168.1.254 GW:192.168.1.254 |
| |
| Network B |
+--------------------------------------------------+

  1. 查询 IP 封包的目标 IP 地址:
    当 PC01 有 IP 封包需要传送时,主机会查阅 IP 封包头部的目标 IP 地址;

  2. 查询本机的路由配置:
    PC01 主机会分析自己的路由表,当发现目标 IP 与本机 IP 的 Net_ID 相同时(同一网段),则PC01 会直接透过局域网功能,将数据包直接传送给目的地主机。

  3. 查询默认网关(default gateway):
    但在本案例中, PC01 与 PC11 并非在同一网段,因此 PC01 会分析路由表当中是否有其他相符合的路由设定,如果没有的话,就直接将该 IP 封包送到默认网关(default gateway)上头去,在本案例当中 default gateway 则是Server A。

  4. 送出封包至 gateway 后,不理会封包流向:
    当 IP 由 PC01 送给 Server A 之后, PC01 就不理会接下来的工作。而 Server A 接收到这个封包后,会依据上述的流程,也分析自己的路由表,然后向后继续传输到正确的目的地主机上。

TCP 协议

TCP 协议处于四层参考模型的第三层,即传输层。同一层的还有 UDP 协议。TCP 和 UDP 的区别是:TCP 是可靠的,面向连接的,基于字节流的服务;UDP 是不可靠的,无连接的,面向数据块的服务。

解释如下:

  • 每次使用 TCP 传输数据时,都要先建立一对一的连接,即面向连接的。而使用 UDP 时不必先建立连接,而是直接将数据广播出去就可以,即无连接;
  • 因为 TCP 必须先建立连接,所以 TCP 传输的速度要比 UDP 慢;
  • TCP 使用一系列机制来保证数据的可靠传输,包括数据确认机制,超时重传机制等。
    发送 TCP 数据时,应用层需将数据写入到 OS 提供的 buffer 里面,操作系统将其看作一连串的,没有边界的数据流,通过相对序号进行定位;而发送 UDP 数据时,应用层交给 OS 多大的数据包,操作系统就直接发送出去。根本不考虑效率,如果数据太大,可能会在 IP 层进行分片,如果数据太小,则每个数据包的有效载荷会比较低,浪费带宽;

TCP 报头格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|4 bits|  6 bits |  6 bits |          16 bits           |
+----------------+--------------------------------------+
| Source Port | Destination Port |
+--------------------------+----------------------------+
| Sequence Number |
+-------------------------------------------------------+
| Acknowledge Number |
+----------------+---------+----------------------------+
|Data |Reserved | Code | Window |
|Offset| | | |
+----------------+--------------------------------------+
| Checksum | Urgent Pointer |
+--------------------------+----------------------------+
| Options(0~40 bytes) |
+-------------------------------------------------------+
  • Source Port & Destination Port(来源和目的端口):指明该 TCP 报文是由哪一个应用程序发送给哪一个应用程序的。因为端口号标示这应用层的一个服务进程;
  • Sequence Number(序号):序号表明该报文段在整个数据流中相对于开始位置的偏移量;
  • Acknowledge Number(确认号):确认号表明该报文是对对端的哪一个报文的确认,特别声明的是,只有当 ACK 标志为 1 时,确认号才有效。TCP 的数据确认机制就是通过这两个字段来实现的;
  • Data Offset:标识该 TCP 头部有多少个 4 字节,共表示最长 15x4=60 字节。同IP头部;
  • Reserved:保留不用,以便于将来扩展;
  • Code(Control Flag,控制标志码):共 6 位:S、A、F、U、R、P,含义分别为 S –> SYN,若为 1,表明这是一个请求报文。A –> ACK,若为 1,表明确认号有效,这是一个确认报文。F –> FIN,若为 1,表明这是一个断开连接的请求报文。U –> URG,若为 1,表明紧急指针有效。R –> RST,若为 1,表明这是一个复位报文段,接收端会清空自己的发送缓冲区。P –> PSH,若为 1,提示接收端应用程序应立即从缓冲区中读走数据;
  • Window(滑动窗口):用于流量控制,告诉对端自己的缓冲区大小,用于 TCP 的滑动窗口机制;
  • Checksum(确认检查码):由发送端对 TCP 头部和数据部分进行 CRC 循环冗余校验后填充,接收端以此确定该数据报是否损坏;
  • Urgent Pointer(紧急指针):若 URG 标志为 1,则紧急指针有效,指明 TCP 带外数据的相对位置;
  • Options(选项):目前此字段仅应用于表示接收端可以接收的最大数据区段容量,若此字段不使用, 表示可以使用任意数据区段的大小,这个字段较少使用。选项最大长度为 40 字节,计算方法和 IP 头部选项的计算方法一致.

No comments:

Post a Comment