注:本文为 “ TCP/IP | 报头解析 / 通信流程” 相关文章合辑。
未整理去重。
如有内容异常,请看原文。
TCP 报文头部
「已注销」于 2019 - 08 - 18 16:27:42 发布
主要学习端口号、三次握手、四次挥手
TCP 包头
-
TCP 报文固定长度为 20 字节加上可变长度。
-
TCP 包头如下图所示:
-
源端口、目标端口:计算机上的进程间通信需借助计算机端口,且某个时刻一个计算机端口仅能被一个进程占用。通过指定源端口和目标端口,可明确通信的两个进程。源端口和目标端口用 16 位表示,由此推算计算机端口个数为 (2^{16}) 个。
-
序列号:表示本报文段所发送数据的第一个字节的编号。在 TCP 连接所传送的字节流中,每个字节都会按顺序编号。由于序列号由 32 位表示,所以每 (2^{32}) 个字节,序列号会回绕,再次从 0 开始。
-
确认号:表示接收方期望收到发送方下一个报文段的第一个字节数据的编号。即告知发送方,希望其下次发送的数据的第一个字节数据的编号为此确认号。
-
数据偏移:表示 TCP 报文段的首部长度,共 4 位。因 TCP 首部包含长度可变的选项部分,所以需指定该 TCP 报文段的长度。它指出 TCP 报文段的数据起始处距离 TCP 报文段的起始处的距离。该字段以 32 位(即 4 个字节)为计算单位,4 位二进制最大表示 15,所以数据偏移意味着 TCP 首部最大为 60 字节。
-
URG:表示本报文段中发送的数据是否包含紧急数据。仅当 URG = 1 时,后面的紧急指针字段(urgent pointer)才有效。
-
ACK:表示前面的确认号字段是否有效。只有当 ACK = 1 时,前面的确认号字段才有效。TCP 规定,连接建立后,ACK 必须为 1,带有 ACK 标志的 TCP 报文段称为确认报文段。
-
PSH:提示接收端应用程序应立即从 TCP 接收缓冲区中读取数据,以便为后续数据接收腾出空间。若 PSH = 1,则表示对方应立即将数据提交给上层应用,而非缓存起来。若应用程序未读取接收到的数据,数据将一直停留在 TCP 接收缓冲区中。
-
RST:若收到 RST = 1 的报文,表明与主机的连接出现严重错误(如主机崩溃),必须释放连接,然后重新建立连接。或者说明上次发送给主机的数据存在问题,主机拒绝响应。带有 RST 标志的 TCP 报文段称为复位报文段。
-
SYN:在建立连接时使用,用于同步序号。当 SYN = 1,ACK = 0 时,表示这是一个请求建立连接的报文段;当 SYN = 1,ACK = 1 时,表示对方同意建立连接。SYN = 1,说明这是一个请求建立连接或同意建立连接的报文。仅在前两次握手中,SYN 才置为 1,带有 SYN 标志的 TCP 报文段称为同步报文段。
-
FIN:表示通知对方本端要关闭连接,标记数据是否发送完毕。若 FIN = 1,即告知对方:“我的数据已发送完毕,你可以释放连接了”。带有 FIN 标志的 TCP 报文段称为结束报文段。
-
窗口大小:表示当前允许对方发送的数据量,即告知对方,从本报文段的确认号开始允许对方发送的数据量。达到此值后,需 ACK 确认后才能继续传送后面的数据。此值由 Window size value * Window size scaling factor(此值在三次握手阶段通过 TCP 选项 Window scale 协商得到)得出。
-
校验和:提供额外的可靠性。
-
紧急指针:标记紧急数据在数据字段中的位置。
-
选项部分:其最大长度可根据 TCP 首部长度推算。TCP 首部长度用 4 位表示,选项部分最长为:((2^{4}-1)\times4 - 20 = 40) 字节。
常见选项
-
最大报文段长度:Maxium Segment Size,MSS,通常为 1460 字节。
-
窗口扩大:Window Scale。
-
时间戳:Timestamps。
1. 最大报文段长度 MSS(Maximum Segment Size)
指明自己期望对方发送 TCP 报文段时数据字段的长度,例如 1460 字节。数据字段的长度加上 TCP 首部的长度才等于整个 TCP 报文段的长度。MSS 既不宜设置得过大,也不宜设置得过小。若选择过小,极端情况下,TCP 报文段可能仅含有 1 字节数据,在 IP 层传输的数据报开销至少有 40 字节(包括 TCP 报文段的首部和 IP 数据报的首部),这样网络利用率不会超过 1/41。若 TCP 报文段非常长,在 IP 层传输时可能需分解成多个短数据报片。在终点需将收到的各个短数据报片装配成原来的 TCP 报文段,且传输出错时还需重传,这些都会增加开销。因此,MSS 应尽可能大,只要在 IP 层传输时不需要再分片即可。在连接建立过程中,双方都会将自己能够支持的 MSS 写入该字段。MSS 仅出现在 SYN 报文中,即 MSS 出现在 SYN = 1 的报文段中。
MTU (maximum transmission unit,大传输单元)和 MSS 值的关系:
MTU = MSS + IP Header + TCP Header
通信双方最终的 MSS 值 = 较小 MTU - IPHeader - TCP Header
2. 窗口扩大
为扩大窗口,由于 TCP 首部的窗口大小字段长度为 16 位,其表示的最大数为 65535。但随着时延和带宽较大的通信(如卫星通信)的出现,需要更大的窗口来满足性能和吞吐率需求,因此产生了窗口扩大选项。
3. 时间戳
可用于计算 RTT(往返时间)。发送方发送 TCP 报文时,将当前时间值放入时间戳字段,接收方收到后在发送确认报文时,将该时间戳字段的值复制到确认报文中,发送方收到确认报文后即可计算出 RTT。时间戳还可用于防止回绕序号 PAWS,也可用于区分相同序列号的不同报文。因为序列号用 32 位表示,每 (2^{32}) 个序列号就会产生回绕,使用时间戳字段可容易地区分相同序列号的不同报文。
源端口和目标端口
-
下层协议为上层提供服务,在传输层通过源端口和目标端口来区分上层应用程序。
-
端口号用于区分同一台主机上的不同程序,是不同程序的唯一标识。
-
端口号总共 16 位,即 (2^{16} = 65535),这意味着一台主机最多能运行 65535 个与网络相关的应用程序。在某些情况下,一个应用程序可能占用多个端口,但一般不会达到此数量,因此端口数通常足够使用。
-
请求报文:
-
目标端口 ==> 服务器,这是约定俗成的。
-
源端口 ===> 客户端,随机分配。
-
-
响应报文:
-
源端口 ==> 服务器,约定俗成。
-
目标端口 ===> 客户端,随机分配。
-
-
连接会话的区别:
-
eg:
-
① 使用 xshell 连接 VMware 中的 Linux 时,当 xshell 连接时选择 ssh 复制生成的终端属于会话。会话属于同一链路,会话不会分配端口。
-
② 使用 xshell 再建立一个连接属于连接:连接会创建一条新的链路,重新分配端口。
-
-
-
连接可利用
ss -tn
查看。
[root@centos7 ~]# ss -tn
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 0 192.168.38.7:22 192.168.38.1:7915
ESTAB 0 52 192.168.38.7:22 192.168.38.1:1321
常见服务与其对应的端口
-
tcp
-
http 80
-
https 443
-
ssh 22
-
telnet 23
-
ftp 21
-
smtp 25
-
pop 110
-
imap 143
-
mysql 3306
-
oracle 1521
-
sql server 1433 1434
-
查询端口
(有时开发的服务需要对外提供服务,此时需要查询确认端口未被占用,可查询哪些端口被占用)
~] vim /etc/services (/etc/services 记录了一些著名服务使用的协议和端口号)
TCP 协议 PORT
-
1)传输层通过 port 号确定应用层协议。
-
2)Port number:
-
3)tcp:传输控制协议,面向连接的协议;通信前需建立虚拟链路;结束后拆除链路,范围是 0 - 65535。
-
4)udp:User Datagram Protocol,无连接的协议,范围是 0 - 65535。
-
5)IANA: 互联网数字分配机构(负责域名,数字资源,协议分配)。
-
0 - 1023:系统端口或特权端口(仅管理员可用),众所周知,永久分配给固定的系统应用使用,如 22/tcp (ssh), 80/tcp (http), 443/tcp (https)。
-
1024 - 49151:用户端口或注册端口,但要求并不严格,分配给程序注册为某应用使用,例如:
1433 /tcp (SqlServer)
-
1521 /tcp (oracle)
3306 /tcp (mysql)
11211 /tcp/udp (memcached)
- 49152 - 65535:动态端口或私有端口,客户端程序随机使用的端口。
其范围的定义:/proc/sys/net/ipv4/ip_local_port_range ,在特定场合需要修改此值;一般反向代理时,此值需要改大(1024 65535)。
[root@centos7 ~]# ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:111 *:*
LISTEN 0 128 *:6000 *:*
LISTEN 0 128 *:47220 *:*
LISTEN 0 5 192.168.122.1:53 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 128 127.0.0.1:631 *:*
-l
用于显示处于监听的端口,相当于显示默认开启的软件。
面试时经常会被问到哪个端口被哪个程序占用,可通过以下命令查询:
① ss -tnlp (p 选项)
② lsof -i :22(查询 22 端口被哪个软件占用)
序号
当数据报文较大时,会涉及切包(因为在数据链路层帧结构中数据的最大长度是 1500 字节)。切包后,每个包都有一个编号。
-
序号的作用之一:接收方接收到数据时,可根据序号进行组合。
-
序号的作用之二:传输时,丢包有序号,有助于减少重传的包的数量。
-
如何验证丢包?—> 通过确认号。
确认号
确认号用于通信双方中接收方确认收到的数据包。
-
如何确认?
-
① eg:发送第 #个包时,回复确认号为 #。
-
② eg:发送第 #个包时,回复确认号为# + 1,希望对方下次发送下一个包。
-
-
网络通信采用的是②这种机制。
-
报文包的个数总共 32 位,有 (2^{32}) 个报文编号。
-
仅靠编号无法区分报文时,可添加时间戳。
-
接收方回应发送方:举例:
确认号:ack < ==== > 序列号:seq (从上往下分析)
-
① client 向 server 请求:
-
seq 10:表示 client 目前发送第 10 个包给 server。
-
ack 1: 表示 client 收到了 server 刚给它发的第 0 个包。
-
-
② server 向 client 响应:
-
seq 1: server 应 client 要求,将 1 包发送给 client。
-
ask 11:server 告诉 client ,client 刚给它的 10 包已收到。
-
-
③… 以此类推
这种每次都收发确认的逻辑效率不高。提高效率的方式是阶段性地回答收到还是未收到,这涉及窗口的问题。
窗口
固定窗口
窗口用于确定发送多少个包后进行一次确认。
-
若 Window size = 1,则表示一个包确认一次:
-
窗口 Window size = 3,表示三个包确认一次。
这种窗口固定的逻辑并非十分理想,因为窗口固定,而网络状态并非稳定不变。
滑动窗口
工作中常用滑动窗口。
发送方 < ==== > 接收方。
原理:刚开始发送方会假设接收方一次能接受 #个数据包,接收方回应发送方能接收的具体数据包数量(若能全收,发送方将增大 #值,再进行尝试),此时相当于双方协商。在发送过程中,还会根据网络状态实时调整,因此 TCP 可以进行流量控制。
-
目前在 tcp 包头中,窗口总共 16 位,则一次性的报文最大为 (2^{16} = 65536),但随着网络带宽的增加,这个值仍显较小。
-
引入 Window size scaling factor 以便扩大窗口大小。
-
窗口扩大因子(Window size scaling factor )此值是在通信双方第一次通信时协商得出的,因子大小固定,但窗口大小可变。
-
通信双方可能各有各自的因子,传输时 = 自己的因子大小 * 每次发送的窗口大小。
数据偏移
数据报文的头部长度不固定,其中部分内容是可选的。
-
TCP 报文头部的固定内容:每一行 32bit(4 字节)* 5 行 = 20 字节。
-
可变部分:
保留
保留部分预留了一些数据位,目前处于未使用状态。
校验和
用于校验数据是否被破坏
紧急指针
选项部分
-
常见选项
-
最大报文段长度:Maxium Segment Size,MSS,通常 1460 字节。此最大报文长度是根据帧的数据位最大为 1500,帧的数据位包括网络层的头部和传输层的头部(各 20 字节固定长度)得出的。
-
窗口扩大:Window Scale
-
时间戳:Timestamps
六个特殊标志
在保留位之后是六个特殊标记,这六个标记的作用分别为:
标志位 | 含义 | 作用 |
---|---|---|
URG | 表示紧急指针中内容是否有效 | 若 URG = 1,则固定长度最后 16bit 的紧急指针有效; URG = 0 则紧急指针内容无效 |
RST | reset,连接复位 | 若 RST = 1,说明与主机的连接出现严重故障,需重新建立连接,带 RST 标志的 TCP 报文段为复位报文段 RST = 0:表示当前 TCP 连接正常,没有出现需要复位连接的情况。 |
PSH | 控制数据在缓冲区的处理方式 | PSH = 1 时,网卡收到数据后立即传给应用程序,不再缓存; PSH = 0 时,为默认情况,数据先放在内核中 TCP 缓冲区,等待一段时间再复制至应用程序 |
重点掌握以下三个特殊标志
ACK、SYN、FIN 与建立 TCP 的通信息息相关。主机利用 TCP 协议进行通信之前需要建立 TCP 连接,建立连接的作用是确保通信双方可以进行安全可靠的通信。
三次握手
建立连接的过程一般被称为 TCP 的三次握手:
三次握手的实现过程如下:如上图所示,通常未进行通信过的两个主机,第一次发起请求的一般为客户端。seq 为序号,ack 为确认号,大写 ACK、SYN、FIN 为三个特殊标记。
-
① 第一次发起请求时:client 设置 SYN = 1,seq = x
抓包软件可看到 tcp 请求连接建立的标志位 SYN = 1
-
② server 收到时立即回应:server 回应 SYN = 1,ACK = 1,seq = y,ack = x + 1。
-
③ client 收到是立即回应:client 回应 ACK = 1,seq = x + 1,ack = y + 1。
-
④ 以上①②③步骤完成后,TCP 三次握手成功,建立连接,双方可进行数据通信。
在 TCP 三次握手时,两个主机的网络连接状态会发生变化:
-
① server 端必须事先将能够接受 client 服务的端口处于 LISTEN 状态
-
② 在访问 server 之前,client 的随机端口未被打开,当 client 去访问 server 时,随机端口打开,发起 TCP 建立连接请求,此时 client 的网络状态自动变为 SYN - SENT 状态
-
③ server 端收到 client 端的连接建立请求后,server 的网络状态由 listen 转变为 SYN - RCVD
-
④ client 发送连接确认后,client 的网络状态由 SYN - SENT 变为 ESTAB - LISHED
-
⑤ server 再次收到连接确认时,server 的网络状态有 SYN - RCVD 变为 ESTAB - LISHED
即:server : LISTEN --> SYN - RCVD --> ESTAB - LISHED
client : SYN - SENT --> ESTAB - LISHED
四次挥手
TCP 的四次挥手过程如下:断开连接请求可以由 client 或 server 发起
图中当 server 端收到 client 的断开请求时,可能由于传输的数据没有传完,因此 server 端不会立即同意断开请求,仍可继续给 client 端发送数据。此阶段数据传输是单向的(半双工,半关闭)。
当 server 端同意断开请求连接时,client 的网络状态不会立即切换。因为先发的报文不一定比 server 同意断开请求的报文先到达,需要等待 2MSL(报文最长存活时间)时间,确认 server 端的数据全部接收后,才会改变网络状态。
有限状态机 FSM:Finite State Machine
-
CLOSED:没有任何连接状态
-
LISTEN:侦听状态,等待来自远方 TCP 端口的连接请求
-
SYN - SENT:在发送连接请求后,等待对方确认
-
SYN - RECEIVED:在收到和发送一个连接请求后,等待对方确认
-
ESTABLISHED:代表传输连接建立,双方进入数据传送状态
-
FIN - WAIT - 1:主动关闭,主机已发送关闭连接请求,等待对方确认
-
FIN - WAIT - 2:主动关闭,主机已收到对方关闭传输连接确认,等待对方发送关闭传输连接请求
-
TIME - WAIT:完成双向传输连接关闭,等待所有分组消失
-
CLOSE - WAIT:被动关闭,收到对方发来的关闭连接请求,并已确认
-
LAST - ACK:被动关闭,等待最后一个关闭传输连接确认,并等待所有分组消失
-
CLOSING:双方同时尝试关闭传输连接,等待对方确认
有限状态机
客户端先发送一个 FIN 给服务端,自己进入了 FIN_WAIT_1 状态,这时等待接收服务端的报文,该报文会有三种可能:
-
① 只有服务端的 ACK
-
② 只有服务端的 FIN
-
③ 基于服务端的 ACK,又有 FIN
-
只收到服务器的 ACK,客户端会进入 FIN_WAIT_2 状态,后续当收到服务端的 FIN 时,回应发送一个 ACK,会进入到 TIME_WAIT 状态,这个状态会持续 2MSL (TCP 报文段在网络中的最大生存时间,RFC 1122 标准的建议值是 2min)。客户端等待 2MSL,是为了当最后一个 ACK 丢失时,可以再发送一次。因为服务端在等待超时后会再发送一个 FIN 给客户端,进而客户端知道 ACK 已丢失。
-
只有服务端的 FIN 时,回应一个 ACK 给服务端,进入 CLOSING 状态,然后接收到服务端的 ACK 时,进入 TIME_WAIT 状态。
-
同时收到服务端的 ACK 和 FIN,直接进入 TIME_WAIT 状态。
客户端的典型状态转移
客户端通过 connect 系统调用主动与服务器建立连接,connect 系统调用首先给服务器发送一个同步报文段,使连接转移到 SYN_SENT 状态。
此后 connect 系统调用可能因为如下两个原因失败返回:
-
如果 connect 连接的目标端口不存在(未被任何进程监听),或者该端口仍被处于 TIME_WAIT 状态的连接所占用(见后文),则服务器将给客户端发送一个复位报文段,connect 调用失败。
-
如果目标端口存在,但 connect 在超时时间内未收到服务器的确认报文段,则 connect 调用失败。
connect 调用失败将使连接立即返回到初始的 CLOSED 状态。如果客户端成功收到服务器的同步报文段和确认,则 connect 调用成功返回,连接转移至 ESTABLISHED 状态。
当客户端执行主动关闭时,它将向服务器发送一个结束报文段,同时连接进入 FIN_WAIT_1 状态。若此时客户端收到服务器专门用于确认目的的确认报文段,则连接转移至 FIN_WAIT_2 状态。当客户端处于 FIN_WAIT_2 状态时,服务器处于 CLOSE_WAIT 状态,这一对状态是可能发生半关闭的状态。此时如果服务器也关闭连接(发送结束报文段),则客户端将给予确认并进入 TIME_WAIT 状态。
客户端从 FIN_WAIT_1 状态可能直接进入 TIME_WAIT 状态(不经过 FIN_WAIT_2 状态),前提是处于 FIN_WAIT_1 状态的服务器直接收到带确认信息的结束报文段(而不是先收到确认报文段,再收到结束报文段)。
处于 FIN_WAIT_2 状态的客户端需要等待服务器发送结束报文段,才能转移至 TIME_WAIT 状态,否则它将一直停留在这个状态。如果不是为了在半关闭状态下继续接收数据,连接长时间地停留在 FIN_WAIT_2 状态并无益处。连接停留在 FIN_WAIT_2 状态的情况可能发生在:客户端执行半关闭后,未等服务器关闭连接就强行退出了。此时客户端连接由内核来接管,可称之为孤儿连接(和孤儿进程类似)。
Linux 为了防止孤儿连接长时间存留在内核中,定义了两个内核参数:
-
/proc/sys/net/ipv4/tcp_max_orphans 指定内核能接管的孤儿连接数目
-
/proc/sys/net/ipv4/tcp_fin_timeout 指定孤儿连接在内核中生存的时间
报头(详解)
QJue 于 2023 - 05 - 07 20 : 26 : 23 发布
报头详解
- IPV4 报头详解
- 第一行内容(Version、IHL、Type of Service、Total Length)
- 第二行内容(Identification、Flangs、Frangment Offset)
- 第三行内容(Time to Live、Protocol、Header Checjsum)
- 第四行内容(Source IP Address)
- 第五行内容(Destination ip address)
- 第六行内容(Options、Padding)
- UDP 报头详解
- 第一行内容(Source Port、Destination Port)
- 第二行内容(Length、Checksum)
- TCP 报头详解
- 第一行内容(Source Port、Destination Port)
- 第二行内容(Sequence Number)
- 第三行内容(Acknowledgement Number)
- 第四行内容(Data Offset、Reserved、Flags)
IPV4 报头详解
(网络层报头)
IPV4 报头共有六行,每一行 32bit、4 字节,报头长度为 20 - 60 字节;
前五行为固定头部部分,共 20 字节;
最后一行为可选部分,取值范围为 0 - 40bits,一般为空。
第一行内容(Version、IHL、Type of Service、Total Length)
-
Version:版本
- 用于区分不同 IP 版本
- 大小:4bits
- IPV4 = 0100(代表版本 4 封装)
-
IHL:IP 头部长度(I:IP;G: 头部,L: 长度)
- 因为 Option 可选部分不固定,导致 IP 头部长度不固定,所以需要标识头部长度
- IP 报文长度必须是 4 字节的整数倍,如果不是,需要最后的填充字段加以填充(用 0 补齐)
- 大小:4bits
- 范围:20 - 60 字节(20 字节为固定头部部分大小)
- 默认值:5/0101 - 15/1111
0101 = 5 5x4bits = 20 字节(最小)------- 1111 = 15 15x4bit = 60 字节
-
Type of Service:服务类型
- 对流量进行区分和识别,方便后续的抓取流量。
- 大小:8bits
- 区分方法:
-
8bit >> |0|1|2|3|4|5|6|7|
-
将 8bits 分为 3 + 5 两部分;
-
前三位二进制来定义优先级,把流量分为八种等级,0 为正常转发,大多数时候这样认为 7 最高,但可以人为定义;
-
最后一位 bits 为 0;
-
前三位定义的优先级等级分为:
等级 优先级 0(000) Routine(普通) 1(001) Priority(优先) 2(010) Immediate(快速) 3(011) Flash(闪速) 4(100) Flash Override(极速) 5(101) Critic/ECP(关键) 6(110) Internetwork Control(网间控制) 7(111) Network Control(网络控制)
-
-
将 8bits 分为 6 + 2 两部分;
- 前 6 位二进制定义 DSCP 区分服务代码点 —DS 字段,是 IP 优先级和服务类型字段的组合,把流量区分 64 种等级,0 - 63;
- 其中前三位区分 IP 优先级,与上面表格优先级区分相同;
- 第四位为延迟,0 —>Normal delay(正常延迟);1 —>Low delay(低延迟);
- 第五位为吞吐量,0 —>Normal Throughput(正常吞吐量);1 —>High Throughput(高吞吐量);
- 第六位为可靠性,0 —> 为 Normal Reliability(正常可靠性);1 —>High Reliability(高可靠性)
- 后 2 位是显示拥塞通知字段 —ECN 字段,用于 QS,告诉其他路由器我已经转发不了了,最后一位为 0;
-
- PHB 逐跳行为
- 有的支持 IP.P,有的支持 DSCP,
- 以上两种都识别,兼容模式,用 PHB 识别 DSCP,如果没有识别 DSCP 还是按照 PHB 的识别
-
Total Length:总长度
- 计算实际报文数据的长度
- 总长度 = IP 头部长度 + 数据长度
- 大小:16bits
- 总长度取值范围为 0 - 65535 字节,最大长度为 65535 字节(2 的 16 次方 - 1),链路只允许 1500byte,所以一般都需要 MTU 分片
第二行内容(Identification、Flangs、Frangment Offset)
为了数据分片后的重组
-
Identification:标识符
- 重组数据时(解封装)标识符一样代表来自同一个数据,就是让目标主机确定一个新到达的分段是哪一个数据流的
- 大小:16bits
- 随机的空间为 2 的 16 次方 = 65535
- 原理:
- 当原始报文大小超过 MTU,那么就必须将原始数据进行分片。
- 每个被分片的报文大小不得超过 MTU,而这个字段还将在同一原始文件被分片的报文上打上相同的标记,一边接收设备可以识别出属于同一个报文的分片,“类似于进程号”— 标识符。
- 相同的标识符使分片后的各数据报片最后能正确地重装成为原来的数据报。
-
Flangs:标记位
- 大小:3bits
- 标识数据是否分片
- 标记位被分为了三部分:
- 保留位:Reserved
- 没有被使用
- 不分片位:DF (Don’t Fragment)
- DF = 1:不允许分片(收到数据时,可以直接解封装)
- DF = 0:允许分片(收到数据时,需要先重组数据,再解封装)
- 更多分片:MF (More Fragment)
- MF = 1:表示后面有分片
- MF = 0:表示当前是最后一个分片
- 当上一位 DF = 0 时才看这一位
- 重组数据时,需要通过这一位来确保数据分片全部收到后再开始重组,所以当 MF = 0 时才开始重组数据
- 保留位:Reserved
-
Frangment Offset:分片偏移
- 标识某个分片在分组中的位置
- 大小:13bits
- 如果没有分片,该字段为 0;如果有分片,片偏移以 8 个字节为偏移单位,每个分片的长度一定是 8 字节 (64 位) 的整数倍。
第三行内容(Time to Live、Protocol、Header Checjsum)
-
Time to Live:生存时间(TTL)
- (网络层防环机制)用于三层防环用的,防止数据包发生环路
- 大小:8bits
- TTL 值:255(最大,2 的 8 次 = 255),TTL 并不是一个真正时间值,用来表示跳数的大小,即数据包能传多少跳;不同的操作系统 TTL 值不同
- 原理:
- 数据包每经过一个路由器,TTL 值就减 1 ,当 TTL = 0 时,丢弃这个报文,从而阻止报文在网络上无限传输。
-
Protocol:协议
- 标识出传输层的地址或协议号;也就是说表示数据要进行什么样的上层服务,应该交给自己上一层的哪个协议(ICMP/IGMP/OSPF 都介于网络层和传输层之间,但一般视作网络层,因为都需要用 IP 报头封装),告诉主机的 IP 层应该将数据交给哪个上层处理过程
- 大小:8bits
- 协议号范围:0 - 255(0 一般不用),1 代表 ICMP,6 代表 TCP,17 代表 UDP,89 代表 OSPF
-
Header Checjsum:报头校验和
- 用于 IP 首部校验,为了防止其他人篡改 IP 头部,要是校验失败不再解封装直接丢弃该报文
- 大小:16bits
- 计算方法:
- 校验核的 16 位字段只对首部查错,不包括数据部分,数据部分由高层协议校验
- 经过路径的每一跳,路由器都要重新计算出的首部检验和并与此字段进行比对,如果不一致,此报文将会被丢弃
- 重新计算的必要性是因为每一跳的一些首部字段(如 TTL、Flag、Offset 等)都有可能发生变化,不检查数据部分是为了减少工作量
- 数据区的错误留待上层协议处理 ——(UDP)和(TCP)都有检验和字段;此处的检验计算方法不使用 CRC
第四行内容(Source IP Address)
- Source IP Address:源 IP 地址
- 发送端 IP 地址,Web 应用中,源 IP 不能是受限广播 IP
- 大小:32bits
第五行内容(Destination ip address)
- Destination ip address:目的 IP 地址
- 接收端 IP 地址;255.255.255.255 为受限广播,路由器将丢弃该报文;x.x.x.255 直接广播,该报文将被发送到 x.x.x.0/24 子网的每一台主机上
- 大小:32bits
第六行内容(Options、Padding)
-
Options:可选字段
- Option 字段很少使用,用于控制、转发要求、测试等
- 包括机制:
- 松散路由(LSR - Loose Source Route):只要以此经过记录的 IP,多经过几个路由器不要紧,网关可以不遵守
- 严格路由(SSR - Strict Source Route):记录出去的 IP,数据包严格按照这个记录去转发,并且在转发过程中将源路由替换为路由器地址,不是规定路由则丢弃数据包,最多指定 10 条路由
- 路由记录(RR - Record Route):记录访问一个地址经过的路由器的 IP 地址,长度由始发设备设置,不能被放大,如果到达目的前被填满,则只会记录部分路由
- 时间戳(TS - Time Stamp):与 RR 类似,只是将路由改为时间戳,每个路由器都插入时间戳,用来查看路由之前的传输时长
- 扩展:为了不暴露内网路径,防火墙应丢弃携带 RR Option 和 TS Option 的报文
-
Padding:填充项
(这一项图中没有画出来,但是实际报头中存在这一项)- Option 字段长度需要是 4 字节的整数倍,非整数倍将 PAD 填充
UDP 报头详解
(传输层报头)
UDP 报头共有两行,每一行 32bit、4 字节,报头长度为 8 字节
第一行内容(Source Port、Destination Port)
-
Source Port:源端口号
- 指明发送数据的进程,不需要时可全用 0
- 大小:16bits
-
Destination Port:目的端口号
- 指明目的主机接收数据的进程,在终点交付报文时必须要使用到
- 大小:16bits
第二行内容(Length、Checksum)
-
Length:长度
- 该字段值为报头和数据两部分的总字节数,其最小值是 8(仅有首部)
- 大小:16bits
-
Checksum:检验和
- UDP 检验和作用于 UDP 报头和 UDP 数据的所有位;由发送端计算和存储,由接收端校验;校验 UDP 用户数据报在传输中是否有错,有错就丢弃
- 大小:16bits
TCP 报头详解
(传输层报头)
TCP 报头共有六行,每一行 32bit、4 字节,报头长度为 20 - 60 字节;
前五行为固定头部部分,共 20 字节;
最后一行为可选部分,取值范围为 0 - 40bits,一般为空**
第一行内容(Source Port、Destination Port)
-
Source Port:源端口号
- 指明发送数据的进程
- 大小:16bits
- 进行 TCP 通信时,客户端通常使用系统自动选择的临时端口号,而服务器则使用知名服务端口号(ftp20,ssh22,telnet23,dns53,http80,https443)
-
Destination Port:目的端口号
- 指明目的主机接收数据的进程
- 大小:16bits
- 进行 TCP 通信时,客户端通常使用系统自动选择的临时端口号,而服务器则使用知名服务端口号(ftp20,ssh22,telnet23,dns53,http80,https443)
第二行内容(Sequence Number)
- Sequence Number:序号 / 序列号
- 指发送数据的位置
- 大小:32bits
- 序号用来标识从 TCP 发送端向接入端发送的数据字节流进行编号,可以理解成对字节流的计数
- 序列号不会从 0 或 1 开始,而是建立连接时由计算机随机生成的数字作为初始值,然后将发送过去的字节数累加到初始值上,表示数据的位置
- 此外,在建立连接和断开连接时发送的 SYN 包和 FIN 包虽然不携带任何数据,但也会作为一个字节增加对应的序列号
第三行内容(Acknowledgement Number)
- Acknowledgement Number:确认号
- 指已收到确认应答前一位为止的数据,发送端接受到这个确认应答以后,可以认为以前的数据都已经被正常接受
- 大小:32bits
- 确认号包含发送确认的一端所期望收到的下一个序号;确认号只有在 ACK 标志为 1 时才有效
第四行内容(Data Offset、Reserved、Flags)
-
Data Offset:首部长度
- 用于表示 TCP 报文首部的长度
- 大小:4bits
- 数据偏移是指数据段中的 “数据” 部分起始处距离 TCP 数据段起始处的字节偏移量;其实这里的 “数据偏移” 也是在确定 TCP 数据段头部分的长度,告诉接收端的应用程序,数据从何处开始
-
Reserved:保留位
- 便于扩展新项目
- 大小:6bits
- 为 TCP 将来的发展预留空间,目前必须全部为 0,但即使收到的包在该位上不为 0,此包也不会被丢弃
-
Flags:标志位
- 大小:6bits
- 每一位从左到右,分别是 URG , ACK , PSH , RST , SYN, FIN
- URG
- 标识紧急指针是否有效,表示包中是否有紧急数据需要处理
- 告诉系统此报文段中有紧急数据
- URG = 1 时表示有紧急数据;当 URG = 1 时,后面的紧急指针字段才有效
- URG
via:
-
TCP 报文头部-CSDN博客
https://blog.csdn.net/wdirdo/article/details/99706085 -
报头(详解)-CSDN博客
https://blog.csdn.net/QJueo/article/details/120893485