TCP/IP 协议及数据格式

读懂了 TCP/IP 协议,也就基本了解的网络通信原理。本文是参照研究生教材《网络安全原理与应用》里面的内容加上自己实际抓包数据分析结合而来,去年第一次看这本书,上面读起来枯燥难懂,读一天也看不到一页,感觉说的又大又空,经过一年的网络编程实战之后再回过头来看这本书里面关于 TCP/IP 部分的讲解,解开了我很多的疑问。但是书中也只是讲个大概理论,有的地方描述不当或者不准确,网络上也充斥很杂的一些文章,有好的也有坏的,让人看起来眼花。下面来结合书上的讲解和我自己的理解来聊聊常见的 TCP/IP 协议。

1、TCP/IP 协议体系

为了减少网络设计的复杂性,大多数网络都采用了分层结构。不同的网络,层的数量、名字、内容和功能都不尽相同。相同网络中,一台机器上的第 N 层与另一台机器上的第 N 层利用第 N 层协议进行通信,协议基本上是双方关于如何进行通信所达成的一致。

TCP/IP 参考模型就是一个符合上面描述的网络体系结构。他是依据他的两个主要协议-TCP 和 IP 而命名的。这一网络细分一般是七层:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层,有关于这七层协议想要了解的可以看下百度百科讲解的网络七层协议,这里就不做过多的废话,重点在下面。

2、IP 协议

2.1 概念

IP 协议用于连接多个分组交换网,他提供在具有固定地址长度的主机之间传送数据报,以及根据各个数据包大小的不同,在需要时进行分段和重组大数据报的功能。IP 协议仅限于将数据从源端传送到目的端,而不提供可靠的传输服务。在传送出错时,IP 协议通过互联网控制消息协议(ICMP, Internet Control Message Protocol)报告。

2.2 功能

IP 协议最基本的两个功能:寻址和分段

寻址:IP 协议根据数据报头中所包含的目的地址将数据报传输到目的端,传送过程中对道路的选择称为路由

分段:当一些网络只能传送小数据报时,IP 协议将数据报分段并在报头里面注明。数据包也可以被标记为“不可分段”,如果一个数据报被如此标记,那么在任何情况下都不准对他进行分段,如果因此到不了目的地,那么数据包就会在中途被丢弃。

2.3 IP 协议数据报的头:

2.3.1 IP 协议头部格式

IP协议数据报的头格式.jpg

2.3.2 IP 协议头部数据

下面是我用抓包工具抓到的一个 TCP 断开的四次握手,其他的咱不管,先看第一次发送 FIN 类型数据包的 IP 报头部分

IP数据报.png

最下面的是数据,去掉以前面太网首部的 14 个字节开始是 IP 数据报头部分,下面我们对着上面的格式来解析下

先单独把 IP 报头数据粘贴下来

//字节为单位 Hex+ASCII方式显示
45 00 00 28 a2 ad 40 00 39 06 0f 71 b7 83 87 91 0a 16 46 87

//二进制 bit流显示为
01000101 00000000 00000000 00101000
10100010 10101101 01000000 00000000
00111001 00000110 00001111 01110001
10110111 10000011 10000111 10010001
00001010 00010110 01000110 10000111
字段 位置 含义
版本 0-3 0100 属于 IPv4 版本
头部长 4-7 0101 表示头部长度为 20 个字节(5 x 4 byte = 20 byte)
服务类型 8-31 00000000 ….
总长 32-47 00000000 00101000 IP 数据报总长(不包括以太网首部) 为 40 个字节(40 x 1 byte = 40 byte)
标识 48 - 50 010 保留位为 0 , 不可分段数据报
分段偏移 51 - 63 00000 00000000 数据偏移为 0,数据报属于分组的第一个分段(其实这个数据包是不允许分段的,这里只是一个理论解释)
生命期 64 - 71 00111001 生命期值是 57,理论解释是还可以经过 57 个节点
协议 72 - 79 00000110 值为 6,表示上层为 TCP 协议
头部效验和 80 - 95 00001111 01110001 ….
源地址 96 - 127 10110111 10000011 10000111 10010001 因为 IP 地址在网络中传播是用网络排序(大端)表示,所以直接按顺序解析,16 进制表示:b7.83.87.91,转换成十进制表示为:183.131.135.145
目的地址 128 - 159 00001010 00010110 01000110 10000111 十进制点形式表示为:10.22.70.135
可选项 ~ ~ 没有可选项

2.4 IP 地址分类

2.4.1 IP 地址分类

IP 地址包含网络号和主机号两部分,网络号代表一个子网络,主机号则表示该子网络下某一台具体的主机标号,IP 地址根据功能和用途的不同可以划分为五类。

A、B、C 三类地址是根据网络规模大小来分配给用户的,例如 A 类地址有 24 位的主机号,同一个网络下,一个 A 类地址可以容纳 2^24 - 2 = 16777213 台主机,但是 A 类地址一共只能分配 126 个网络(这里只是做一个理论上的运算,并不代表实际分配情况),所以这类地址一般分配给那些为数不多的大网络。D 类地址用来多播,E 类地址做保留地址。

另外还有一些特殊地址:

2.4.2 子网掩码、超网

传统的 IP 地址分类确定是不能在网络内部使用路由,这样对于较大的网络,例如一个 A 类网络,由于主机数太多而变得难以管理,为此引入了子网掩码以从一个大网络上划分成一些小网络。子网掩码由一系列 0 和 1 构成,通过与 IP 地址做与运算来得到一个 IP 地址的网络号,例如 A 类地址的子网掩码是 255 . 0 . 0 . 0,B 类地址的子网掩码是 255 . 255 . 0 . 0,C 类地址的子网掩码是 255 . 255 . 255 . 0。要是想将一个 B 类地址(例:129 . 145 . 0 . 0)划分为多个小的 C 类网络,只需要将其子网掩码设为 255 . 255 . 255 . 0 就可以了,这样 129 . 145 . 1 . 0 和 129 . 145 . 2 . 0 就属于不同网络了,因为虽然是 B 类地址,但是与给定的子网掩码做与运算出来的网络号不一样了,就属于不同网络。像这样通过子网掩码将一个大网络划分成若干个小网络叫做划分子网。

超网:与子网功能相反,将若干个小网络划分成一个大网络。例如一个单位分配到了 8 个 C 类(前三个字节为网络号)地址:202 . 120 . 224 . 0 ~ 202 . 120 . 231 . 0,只要将其子网掩码设置为 255 . 255 . 248 . 0 就能使这些 C 类网络相通。(PS:这个结果是怎么得来的我现在还不明白,等日后明白了再补上)

3、TCP 协议

3.1 概念

TCP 协议是用于主机到主机的通信协议。他是面向连接的端到端的可靠协议,提供可靠字节流传输和对上层应用提供连接服务。TCP 协议建立在 IP 协议的基础之上,可以根据 IP 协议提供的服务传输大小不定的数据段。IP 协议负责数据的分段、重组及在多种网络和互联的网关间传输数据报。

为了在不可靠的 IP 数据传输服务上实现面向连接的可靠数据传输,TCP 协议使用序列号和应答号来保证其传输的可靠性,TCP 协议是面向字节流的,每个字节都有一个序列号,一个数据段的第一个字节的序列号将随同数据段被发送,并且作为这个数据段的序列号。数据段同时还带有一个应答序号,表明它期望对方下次发送的字节的顺序号。当 TCP 协议传输一个数据段的时候,会同时将其放入重传队列,并启动一个定时器。如果这个数据段的应答能在定时器超时前收到,那么就将它从重传队列中移除,否则重发此数据段。应答未能收到,既可能是接收方未收到所发数据段,也可能是应答本身丢失。

TCP 协议提供了端口来区分他所处理的不同数据流。由于端口号是由操作系统、TCP 协议进程或用户自行确定,所以有可能不唯一。为此将网络地址同端口号组合起来形成套接字保证其在整个互联网络上的唯一性。

3.2 TCP 协议数据报的头

3.2.1 TCP 协议头部格式

TCP协议数据段的头格式.jpg

标志位简写 全写 含义
NS Nonce 有效排除潜在的 ECN 滥用
CWR Congestion Window Reduced 拥塞窗口减少标志
ECE ECN-Echo ECN 标志
URG Urgent 紧急指针有效性标志
ACK Acknowledgment 确认序号有效性标志,一旦一个连接建立起来,该标志总被置为 1
PSH Push Push 标志(接收方应尽快将报文段提交至应用层)
RST Reset 重置连接标志
SYN Synchronization 同步序号标志(建立连接时候使用)
FIN Fin 传输数据结束标志(断开连接时使用)

3.2.2 TCP 报头可选项字段

TCP 报头可选项字段的数据一般拼接格式(不是全部可选项都是这个格式)

类型kind(1byte) + 长度length(1byte) + 值value (length-2byte)

TCP 报头可选项和含义:

kind 字段 长度(单位 byte)
0 End of Option List (EOL) 0 (没有长度,只有类型)
1 No-Operation (NOP) 0 (没有长度,只有类型)
2 Maximum segment size (MSS) 1 (用一个字节来表示该可选项的总长)
3 Window scale 1 (用一个字节来表示该可选项的总长)
4 SACK Permitted 1 (用一个字节来表示该可选项的总长)
5 SACK 1 (用一个字节来表示该可选项的总长)
8 Timestamps 1 (用一个字节来表示该可选项的总长)

3.2.3 TCP 协议头部数据

下面是我用抓包工具抓到的一个 TCP 断开的四次握手,其他的咱不管,先看第一次发送 FIN 类型数据包的 TCP 数据的头部

IP数据报.png

最下面的是数据,去掉以前面太网首部 14 个字节和IP 报头 20 个字节开始是 TCP 数据报头部分,下面我们对着上面的格式来解析下

先单独把 TCP 头部数据粘贴下来

//字节为单位 Hex+ASCII方式显示
00 50 d2 21 de ce 92 2b ba da c8 db 50 11 01 9b 57 64 00 00

//二进制 bit流显示
00000000 01010000 11010010 00100001
11011110 11001110 10010010 00101011
10111010 11011010 11001000 11011011
01010000 00010001 00000001 10011011
01010111 01100100 00000000 00000000
字段 位置 含义
源端口 0 - 15 00000000 01010000 网络字节排序解析,源端口为 80
目的端口 16 - 31 11010010 00100001 目的端口 53793
顺序号 32 - 63 11011110 11001110 10010010 00101011 顺序号为~
应答号 64 - 95 10111010 11011010 11001000 11011011 确认号为~
TCP 首部长度 96 - 99 0101 长度为 20 字节 5 x 4 byte = 29 byte
保留位 100 - 102 000 ~
标记 103 - 111 0 00010001 ACK 位为 1 标记应答号有效,FIN 位为 1 表示该数据包为结束标识数据包
窗口 112 - 127 00000001 10011011 窗口值为 411,标识发送套接字缓存区最大容纳 411 字节数据
效验和 128 - 143 01010111 01100100 ~
紧急指针 144 - 159 00000000 00000000 紧急指针标记位(URG)为 1 时这里的数据才有效
可选项 ~ ~ ~

3.3 TCP 通信数据交互细节和实践

关于 TCP 连接的三次握手、中间数据交互以及断开连接的四次握手理论部分请参考我前面的一片文章套接字(Socket)编程(二) 内部通信原理,这里就不做重复的解释了

3.3.1 TCP 建立连接的三次握手抓包数据部分

首先来看下抓包过程截图

TCP建立连接的三次握手.png

① 客户端发送[SYN]同步消息

//以太网头部+IP报头+TCP报头+TCP数据(字节为单位位 Hex+ASCII方式显示)
88 25 93 02 b7 8c 78 4f 43 5b 56 75 08 00 45 00
00 40 00 00 40 00 40 06 f6 72 0a 16 46 87 cb d0
27 d8 d2 23 01 bb 2e f0 89 c5 00 00 00 00 b0 02
ff ff b3 39 00 00 02 04 05 b4 01 03 03 05 01 01
08 0a 32 a6 80 43 00 00 00 00 04 02 00 00

//提取TCP报头+TCP数据(去掉以太网头部14byte和IP报头20byte)
d2 23 01 bb
2e f0 89 c5
00 00 00 00
b0 02 ff ff
b3 39 00 00
02 04 05 b4 01 03 03 05 01 01 08 0a 32 a6 80 43 00 00 00 00 04 02 00 00

解析:从上面可以解析出源端口号为:0xd23 = 353795;目的端口号:0x01bb = 443;序列号:SEQ = 0x2ef089c5;ACK = 0x00000000;TCP 报头长为:0xb = 11(32 bit),11 x 4 byte = 44 byte,即 TCP 报头长为 44 个字节;窗口大小为 0xffff = 65535 byte; 保留位和标志位:0x002 = 0b000000000010;按位解析标志位为 0b000000010,NS: 0,CWR: 0,ECE: 0,URG: 0,ACK: 0,PSH: 0,RST: 0,SYN: 1,FIN: 0,从解析里面可以看出该报文 ACK 字段无效,只有 SYN 字段有效,是第一个请求连接[SYN]同步数据报; 可选项部分:可以看出该 TCP 报头最后的 24 个字节表示可选项,解析如下

02 04 05 b4            kind = 2, len = 4,MMS Value = 0x05b4 表示MSS = 1460byte
01                     kind = 1  No-Operation
03 03 05               kind = 3,len = 3,value = 0x05  窗口选项偏移5位,即实际窗口大小为 0xffff x 2^5
01                     kind = 1  No-Operation
01                     kind = 1  No-Operation
08 0a 32 a6 80 43 00 00 00 00   kind = 8,len = 10  时间戳选项,Timestamp Value(TSval): 0x32a68043 = 849772611,Timestamp echo reply(TSecr): 0
04 02                  kind = 4,len  =2  SACK Permitted,选择确认选项有效
00 00                  kind = 0  补充够32bit,即4byte的倍数

② 服务器回复[SYN+ACK]消息

//以太网头部+IP报头+TCP报头+TCP数据(字节为单位位 Hex+ASCII方式显示)
78 4f 43 5b 56 75 88 25 93 02 b7 8c 08 00 45 00
00 3c 66 f2 00 00 38 06 d7 84 cb d0 27 d8 0a 16
46 87 01 bb d2 23 f4 36 9f 4a 2e f0 89 c6 a0 12
71 20 a5 e3 00 00 02 04 05 a0 04 02 08 0a d6 c8
42 f0 32 a6 80 43 01 03 03 08

//提取TCP报头+TCP数据(去掉以太网头部14byte和IP报头20byte)
01 bb d2 23
f4 36 9f 4a
2e f0 89 c6
a0 12 71 20
a5 e3 00 00
02 04 05 a0 04 02 08 0a d6 c8 42 f0 32 a6 80 43 01 03 03 08

解析:从上面可以解析出源端口号为:0x01bb = 443;目的端口号:0xd23 = 353795;序列号:SEQ = 0xf4369f4a;ACK = 0x2ef089c6(即第一个包的 SEQ+1,对第一个同步包的确认);TCP 报头长为:0xa = 10(32 bit),10 x 4 byte = 40 byte,即 TCP 报头长为 40 个字节;窗口大小为 0x7120 =28960 byte;

保留位和标志位:0x012 = 0b000000010010;按位解析标志位为 0b000010010,NS: 0,CWR: 0,ECE: 0,URG: 0,ACK: 1,PSH: 0,RST: 0,SYN: 1,FIN: 0,从解析里面可以看出该报文 ACK 字段和 SYN 字段有效,是对第一个连接请求包的确认[SYN+ACK]数据报

可选项部分:可以看出该 TCP 报头最后的 20 个字节表示可选项,解析如下

02 04 05 a0       kind = 2, len = 4,value = 0x05a0 表示MSS = 1440 byte
04 02             kind = 4  SACK Permitted,选择确认选项有效
08 0a d6 c8 42 f0 32 a6 80 43  kind = 8, len = 10 时间戳选项,Timestamp Value(TSval): 0xd6c842f0 = 36033448560,Timestamp echo reply(TSecr): 0x32a68043 = 849772611
01   kind = 1     NOP
03 03 08  kind = 3, len = 3,value = 8 窗口选项偏移8位,即实际窗口大小为 0x7120 x 2^8

③ 客户端回复[ACK]消息,表示连接成功

//以太网头部+IP报头+TCP报头+TCP数据(字节为单位位 Hex+ASCII方式显示)
88 25 93 02 b7 8c 78 4f 43 5b 56 75 08 00 45 00
00 34 00 00 40 00 40 06 f6 7e 0a 16 46 87 cb d0
27 d8 d2 23 01 bb 2e f0 89 c6 f4 36 9f 4b 80 10
10 09 35 75 00 00 01 01 08 0a 32 a6 80 82 d6 c8
42 f0

//提取TCP报头+TCP数据(去掉以太网头部14byte和IP报头20byte)
d2 23 01 bb
2e f0 89 c6
f4 36 9f 4b
80 10 10 09
35 75 00 00
01 01 08 0a 32 a6 80 82 d6 c8 42 f0

解析:从上面可以解析出源端口号为:0xd23 = 353795;目的端口号:0x01bb = 443;序列号:SEQ = 0x2ef089c6;ACK = 0xf4369f4b (即上一个包的 SEQ +1,对上一个同步包的确认);TCP 报头长为:0x8 = 8(32 bit),8 x 4 byte = 32 byte,即 TCP 报头长为 32 个字节;窗口大小为 0x1009 =4105 byte;

保留位和标志位:0x010 = 0b000000010000;按位解析标志位为 0b000010000,NS: 0,CWR: 0,ECE: 0,URG: 0,ACK: 1,PSH: 0,RST: 0,SYN: 0,FIN: 0,从解析里面可以看出该报文 ACK 字段有效,是对上一个服务器确认请求连接包的确认[ACK]数据报

可选项部分:可以看出该 TCP 报头最后的 12 个字节表示可选项,解析如下

01     kind = 1     NOP
01     kind = 1     NOP
08 0a 32 a6 80 82 d6 c8 42 f0  时间戳选项,Timestamp Value(TSval): 0x32a68082 = 849772674,Timestamp echo reply(TSecr): 0xd6c842f0 = 36033448560

3.3.2 TCP 数据交互抓包数据部分

下面来一组 TCP 连接中间交换数据部分

① 客户端发送数据

//以太网头部+IP报头+TCP报头+TCP数据(字节为单位位 Hex+ASCII方式显示)
88 25 93 02 b7 8c 78 4f 43 5b 56 75 08 00 45 00
00 f5 00 00 40 00 40 06 f5 bd 0a 16 46 87 cb d0
27 d8 d2 23 01 bb 2e f0 89 c6 f4 36 9f 4b 80 18
10 09 43 d2 00 00 01 01 08 0a 32 a6 80 82 d6 c8
42 f0  + 193byte TCP数据

//提取TCP报头+TCP数据(去掉以太网头部14byte和IP报头20byte)
d2 23 01 bb
2e f0 89 c6
f4 36 9f 4b
80 18 10 09
43 d2 00 00
01 01 08 0a 32 a6 80 82 d6 c8 42 f0
+ 193byte TCP数据

解析:从上面可以解析出源端口号为:0xd23 = 353795;目的端口号:0x01bb = 443;序列号:SEQ = 0x2ef089c6;ACK = 0xf4369f4b;TCP 报头长为:0x8 = 8(32 bit),8 x 4 byte = 32 byte,即 TCP 报头长为 32 个字节;窗口大小为 0x1009 =4105 byte; 保留位和标志位:0x018 = 0b000000011000;按位解析标志位为 0b000011000,NS: 0,CWR: 0,ECE: 0,URG: 0,ACK: 1,PSH: 1,RST: 0,SYN: 0,FIN: 0,从解析里面可以看出该报文 ACK 字段和 PUSH 有效,希望传输层尽快将数据交到应用层; 可选项部分:可以看出该 TCP 报头最后的 12 个字节表示可选项

② 服务器端回复 ACK 确认

//以太网头部+IP报头+TCP报头+TCP数据(字节为单位位 Hex+ASCII方式显示)
78 4f 43 5b 56 75 88 25 93 02 b7 8c 08 00 45 00
00 34 66 fa 00 00 38 06 d7 84 cb d0 27 d8 0a 16
46 87 01 bb d2 23 f4 36 9f 4b 2e f0 8a 87 80 10
00 76 44 09 00 00 01 01 08 0a d6 c8 43 2e 32 a6
80 82

//提取TCP报头+TCP数据(去掉以太网头部14byte和IP报头20byte)
01 bb d2 23
f4 36 9f 4b
2e f0 8a 87
80 10 00 76
44 09 00 00
01 01 08 0a d6 c8 43 2e 32 a6 80 82

解析:从上面可以解析出源端口号为:0x01bb = 443;目的端口号:0xd23 = 353795;序列号:SEQ = 0xf4369f4b; ACK = 0x2ef08a87(前面数据包的 SEQ(0x2ef089c6) + 193 = 0x2ef08a87 PS:这里需要注意下,很多网络和书上都说这个 ACK 的值应该是上个包的 SEQ + TCP 数据大小 + 1,这种说法是不准确的,拿上个数据来讲,数据的第一个字节序号也就是上个数据包的序号是 0x2ef089c6,那么第二个字节序号就是 0x2ef089c7,现在 TCP 数据一共是 193 个字节,那么接下来的第 194 个字节序号应该是 0x2ef089c6 + 193 = 0x2ef08a87,所以服务器期望收到下个包的序号应该是 0x2ef08a87); TCP 报头长为:0x8 = 8(32 bit),8 x 4 byte = 32 byte,即 TCP 报头长为 32 个字节;窗口大小为 0x0076 = 118 byte; 保留位和标志位:0x010 = 0b000000010000;按位解析标志位为 0b000010000,NS: 0,CWR: 0,ECE: 0,URG: 0,ACK: 1,PSH: 0,RST: 0,SYN: 0,FIN: 0,从解析里面可以看出该报文 ACK 字段有效,对上个数据包的一个确认,表示可以接着传送后面的数据了(从字节编号为 0x2ef08a87 开始),是一个[ACK]确认数据报; 可选项部分:可以看出该 TCP 报头最后的 12 个字节表示可选项

3.3.3 TCP 断开连接的四次握手抓包数据部分

首先来看下抓包过程截图

TCP断开四次握手.png

① 主动断开方发送[FIN]数据报

//以太网头部+IP报头+TCP报头+TCP数据(字节为单位位 Hex+ASCII方式显示)
78 4f 43 5b 56 75 88 25 93 02 b7 8c 08 00 45 00
00 34 89 5e 40 00 39 06 a4 3f 7a e4 48 a5 0a 16
46 87 00 50 d2 1e a9 ba 9e eb 65 ee 19 b0 80 11
03 cc 9e 50 00 00 01 01 08 0a 41 fa 79 05 32 a6
38 20

//提取TCP报头+TCP数据(去掉以太网头部14byte和IP报头20byte)
00 50 d2 1e
a9 ba 9e eb
65 ee 19 b0
80 11 03 cc
9e 50 00 00
01 01 08 0a 41 fa 79 05 32 a6 38 20

解析:从上面可以解析出源端口号为:0x0050 =80;目的端口号:0xd21e =53790;序列号:SEQ = 0xa9ba9eeb;ACK = 0x65ee19b0;TCP 报头长为:0x8 = 8(32 bit),8 x 4 byte = 32 byte,即 TCP 报头长为 32 个字节;窗口大小为 0x03cc =972 byte;

保留位和标志位:0x011 = 0b000000010001;按位解析标志位为 0b000010001,NS: 0,CWR: 0,ECE: 0,URG: 0,ACK: 1,PSH: 0,RST: 0,SYN: 0,FIN: 1,从解析里面可以看出该报文 ACK 字段和 FIN 字段有效,是请求断开连接的[FIN+ACK]数据报

可选项部分:可以看出该 TCP 报头最后的 12 个字节表示可选项,解析如下

01     kind = 1     NOP
01     kind = 1     NOP
08 0a 41 fa 79 05 32 a6 38 20 时间戳选项,Timestamp Value(TSval): 1106934021,Timestamp echo reply(TSecr): 849754144

② 被断开方发送[ACK]数据包,对主动对方数据报进行确认

//以太网头部+IP报头+TCP报头+TCP数据(字节为单位位 Hex+ASCII方式显示)
88 25 93 02 b7 8c 78 4f 43 5b 56 75 08 00 45 00
00 34 00 00 40 00 40 06 26 9e 0a 16 46 87 7a e4
48 a5 d2 1e 00 50 65 ee 19 b0 a9 ba 9e ec 80 10
10 00 1d d9 00 00 01 01 08 0a 32 a6 ac 63 41 fa
79 05

//提取TCP报头+TCP数据(去掉以太网头部14byte和IP报头20byte)
d2 1e 00 50
65 ee 19 b0
a9 ba 9e ec
80 10 10 00
1d d9 00 00
01 01 08 0a 32 a6 ac 63 41 fa 79 05

解析:从上面可以解析出源端口号为:0xd21e =53790;目的端口号:0x0050 =80;序列号:SEQ = 0x65ee19b0;ACK = 0xa9ba9eec ;TCP 报头长为:0x8 = 8(32 bit),8 x 4 byte = 32 byte,即 TCP 报头长为 32 个字节;窗口大小为 0x1000 = 4096 byte;

保留位和标志位:0x010 = 0b000000010000;按位解析标志位为 0b000010000,NS: 0,CWR: 0,ECE: 0,URG: 0,ACK: 1,PSH: 0,RST: 0,SYN: 0,FIN: 0,从解析里面可以看出该报文 ACK 字段有效,是对断开连接请求的确认[ACK]数据报

可选项部分:可以看出该 TCP 报头最后的 12 个字节表示可选项,解析如下

01     kind = 1     NOP
01     kind = 1     NOP
08 0a 32 a6 ac 63 41 fa 79 05 时间戳选项,Timestamp Value(TSval): 849783907 ,Timestamp echo reply(TSecr): 1106934021

③ 被断开方处理完自己的逻辑,发送[FIN]数据报到断开方

//以太网头部+IP报头+TCP报头+TCP数据(字节为单位位 Hex+ASCII方式显示)
88 25 93 02 b7 8c 78 4f 43 5b 56 75 08 00 45 00
00 34 00 00 40 00 40 06 26 9e 0a 16 46 87 7a e4
48 a5 d2 1e 00 50 65 ee 19 b0 a9 ba 9e ec 80 11
10 00 1d d8 00 00 01 01 08 0a 32 a6 ac 63 41 fa
79 05

//提取TCP报头+TCP数据(去掉以太网头部14byte和IP报头20byte)
d2 1e 00 50
65 ee 19 b0
a9 ba 9e ec
80 11 10 00
1d d8 00 00
01 01 08 0a 32 a6 ac 63 41 fa 79 05

解析:从上面可以解析出源端口号为:0xd21e =53790;目的端口号:0x0050 =80;序列号:SEQ = 0x65ee19b0 ;ACK = 0xa9ba9eec ;TCP 报头长为:0x8 = 8(32 bit),8 x 4 byte = 32 byte,即 TCP 报头长为 32 个字节;窗口大小为 0x1000 = 4096 byte; 保留位和标志位:0x011 = 0b000000010001;按位解析标志位为 0b000010000,NS: 0,CWR: 0,ECE: 0,URG: 0,ACK: 1,PSH: 0,RST: 0,SYN: 0,FIN: 1,从解析里面可以看出该报文 ACK 字段和 FIN 字段有效,是被断开方发送的断开连接[FIN+ACK]数据报; 可选项部分:可以看出该 TCP 报头最后的 12 个字节表示可选项,解析如下

01     kind = 1     NOP
01     kind = 1     NOP
08 0a 32 a6 ac 63 41 fa 79 05 时间戳选项,Timestamp Value(TSval): 849783907 ,Timestamp echo reply(TSecr): 1106934021

④ 断开方对被对开放发送的断开数据报发送[ACK]数据报进行确认

//以太网头部+IP报头+TCP报头+TCP数据(字节为单位位 Hex+ASCII方式显示)
78 4f 43 5b 56 75 88 25 93 02 b7 8c 08 00 45 00
00 34 42 6b 40 00 39 06 eb 32 7a e4 48 a5 0a 16
46 87 00 50 d2 1e a9 ba 9e ec 65 ee 19 b1 80 10
03 cc 29 f7 00 00 01 01 08 0a 41 fa 79 1a 32 a6
ac 63

//提取TCP报头+TCP数据(去掉以太网头部14byte和IP报头20byte)
00 50 d2 1e
a9 ba 9e ec
65 ee 19 b1
80 10 03 cc
29 f7 00 00
01 01 08 0a 41 fa 79 1a 32 a6 ac 63

解析:从上面可以解析出源端口号为:0x0050 =80;目的端口号:0xd21e =53790;序列号:SEQ = 0xa9ba9eec;ACK = 0x65ee19b1;TCP 报头长为:0x8 = 8(32 bit),8 x 4 byte = 32 byte,即 TCP 报头长为 32 个字节;窗口大小为 0x03cc =972 byte;

保留位和标志位:0x010 = 0b000000010000;按位解析标志位为 0b000010000,NS: 0,CWR: 0,ECE: 0,URG: 0,ACK: 1,PSH: 0,RST: 0,SYN: 0,FIN: 0,从解析里面可以看出该报文 ACK 字段有效,是对断开连接请求的确认[ACK]数据报

可选项部分:可以看出该 TCP 报头最后的 12 个字节表示可选项,解析如下

01     kind = 1     NOP
01     kind = 1     NOP
08 0a 41 fa 79 1a 32 a6 ac 63 时间戳选项,Timestamp Value(TSval): 1106934042,Timestamp echo reply(TSecr): 849783907

4、UDP 协议

UDP 协议是 IP 协议上层的另一个重要协议,他是面向无连接的、不可靠的数据报传输协议,他仅仅将要发送的数据报传送至网络,并接受从网络上传来的数据报,而不与远端的 UDP 协议模块建立连接。UDP 协议为用户的网络应用程序提供服务。

4.1 UDP 协议数据报头

4.1.1 UDP 协议头部格式

UDP报头.jpg

4.1.2 UDP 协议头部数据

//以太网头部+IP报头+UDP报头+UDP数据(字节为单位位 Hex+ASCII方式显示)
01 00 5e 4b 00 fe f8 32 e4 8a ef e5 08 00 45 00
00 74 49 b6 00 00 01 11 2f 50 0a 16 46 14 ef 4b
00 fe c1 5f 26 e5 00 60 19 b1 00 00 00 58 4f 47
45 4d 52 41 59 2d 4e 42 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 41 4a
52 40 31 32 33 34 35 36 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00

//UDP报头+UDP数据(去掉以太网头部14byte和IP报头20byte)
c1 5f 26 e5 00 60 19 b1
00 00 00 58 4f 47 45 4d 52 41 59 2d 4e 42 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 41 4a 52 40 31 32 33 34 35 36 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00

从上面数据抓包可以看出: 源端口:0xc15f = 49503 目的端口:0x26e5 = 9957 数据包长(UDP 报头加+UDP 数据):0x0060 = 96 byte 效验值:0x18b1

5、结语

对于 TCP/IP 通信的基本原理和过程就总结到这,顺带说下上面的抓包软件叫Wireshark