Linux网络协议栈-TCP/IP协议报文格式解析(内含代码演示)
bigegpt 2024-10-09 07:59 4 浏览
前言:你是否曾有以下苦恼:在编程时虽然会调用网络方面的 API,却不清楚具体原理;会用基本的 ifconfig 等命令,却不太理解其输出;对于长长的 MAC 地址、IP 地址和子网掩码,不了解它们的分配机理;看了网上对路由器、交换机、TCP、UDP、DHCP、DNS 等知识点的介绍,却依旧迷茫。不必担心,你将会循序渐进地牢牢掌握网络方面的知识。围绕 TCP/IP 协议的网络知识非常重要,我们今天使用电脑手机上网聊天、游戏、购物、追剧等,其实都在不自觉地使用 TCP/IP 协议。想要成为编程方面的专家,除了数据结构、算法、设计模式等知识,网络方面的知识也不可或缺。
一、传输层报文
1、TCP数据包的头
typedef struct _TCP_HEADER {
USHORT nSourPort ; // 源端口号16bit
USHORT nDestPort ; // 目的端口号16bit
UINT nSequNum ; // 序列号32bit
UINT nAcknowledgeNum ; // 确认号32bit
USHORT nHLenAndFlag ; // 前4位:TCP头长度;中6位:保留;后6位:标志位16bit
USHORT nWindowSize ; // 窗口大小16bit
USHORT nCheckSum ; // 检验和16bit
USHORT nrgentPointer ; // 紧急数据偏移量16bit
} TCP_HEADER, *PTCP_HEADER ;
2、UDP数据包的头
typedef struct _UDP_HEADER {
USHORT nSourPort ; // 源端口号16bit
USHORT nDestPort ; // 目的端口号16bit
USHORT nLength ; // 数据包长度16bit
USHORT nCheckSum ; // 校验和16bit
} UDP_HEADER, *PUDP_HEADER ;
进入协议栈的过程:(从协议栈出来刚好相反)
二、网络层报文
1、IP头
IP数据包也叫IP报文分组,传输在ISO网络7层结构中的网络层,它由IP报文头和IP报文用户数据组成,IP报文头的长度一般在20到60个字节之间,而一个IP分组的最大长度则不能超过65535个字节。
下图为IP分组的报文头格式,报文头的前20个字节是固定的,后面的可变
版本号 : 4 个 bit ,用来标识 IP 版本号。这个 4 位字段的值设置为二进制的 0100 表示 IPv4 ,设置为 0110 表示 IPv6 。目前使用的 IP 协议版本号是 4 。
首部长度 : 4 个 bit 。标识包括选项在内的 IP 头部字段的长度。
服务类型 : 8 个 bit 。服务类型字段被划分成两个子字段: 3bit 的优先级字段和 4bit TOS 字段,最后一位置为 0 。 4bit 的 TOS 分别代表:最小时延,最大吞吐量,最高可靠性和最小花费。 4bit 中只能将其中一个 bit 位置 1 。如果 4 个 bit 均为 0 ,则代表一般服务。
现在大多数的 TCP/IP 实现都不支持 TOS 特性,但自 4.3BSD Reno 以后的新版系统都对它进行了设置。另外, OSPF 和 IS-IS 都可以根据这些字段的值进行路由策略。而类似 SLIP 这样的协议虽然提供基于服务类型的排队方法,允许对交互型数据优先进行处理,但它的这种排队机制由 SLIP 自身来判断和处理。驱动程序会先查看协议字段(确定是否是 TCP 段),然后检查 TCP 信源和信宿的端口号来判断是否是一个交互服务。
最近, TOS 字段已经作为区分服务( Diffserv )架构的一部分被重新定义了。 Diffserv 比 TOS 定义所允许的处理更加灵活。在 Diffserv 下,能够在一台路由器上定义服务分类( COS ),将数据包归类到这些分类中去。路由器可以根据它们的分类使用不同的优先级对数据包进行转发。每一个排序和转发处理称为一个 PHB 。这个架构也被简称为 COS 。
利用开始的 6 个位构成 DSCP 位,可以使用任意数值或根据区分服务体系结构中预先定义的服务类别,最多可以定义 64 个不同的服务类别并整理到 PHB 中。 ECN 为显式拥塞通知位。当路由器支持该特性时,这些位可以用于拥塞信号( ECN=11 )。
总长度字段 : 16 个 bit 。接收者用 IP 数据报总长度减去 IP 报头长度就可以确定数据包数据有效负荷的大小。 IP 数据报最长可达 65535 字节。
标识字段 : 16 个 bit 。唯一的标识主机发送的每一份数据报。接收方根据分片中的标识字段是否相同来判断这些分片是否是同一个数据报的分片,从而进行分片的重组。通常每发送一份报文它的值就会加 1 。
标志字段 : 3 个 bit 。用于标识数据报是否分片。第 1 位没有使用,第 2 位是不分段( DF )位。当 DF 位被设置为 1 时,表示路由器不能对数据包进行分段处理。如果数据包由于不能分段而未能被转发,那么路由器将丢弃该数据包并向源发送 ICMP 不可达。第 3 位是分段( MF )位。当路由器对数据包进行分段时,除了最后一个分段的 MF 位被设置为 0 外,其他的分段的 MF 位均设置为 1 ,以便接收者直到收到 MF 位为 0 的分片为止。
位偏移 : 13 个 bit 。在接收方进行数据报重组时用来标识分片的顺序。用于指明分段起始点相对于报头起始点的偏移量。由于分段到达时可能错序,所以位偏移字段可以使接收者按照正确的顺序重组数据包。当数据包的长度超过它所要去的那个数据链路的MTU时,路由器要将它分片。数据包中的数据将被分成小片,每一片被封装在独立的数据包中。接收端使用标识符,分段偏移以及标记域的MF位来进行重组。
生存时间 : 8个bit 。 TTL域防止丢失的数据包在无休止的传播。该域包含一个 8 位整数,此数由产生数据包的主机设定。 TTL 值设置了数据包可以经过得最多的路由器数。 TTL的初始值由源主机设置(通常为 32 或 64 ),每经过一个处理它的路由器, TTL 值减 1 。如果一台路由器将 TTL 减至 0 ,它将丢弃该数据包并发送一个 ICMP超时消息给数据包的源地址。注意: TTL值经过PIX时不减1。
协议字段 : 8 个 bit 。用来标识是哪个协议向 IP 传送数据。 ICMP 为 1 , IGMP 为 2 , TCP 为 6 , UDP 为 17 , GRE 为 47 , ESP 为 50 。
首部校验和 :根据 IP 首部计算的校验和码。
源IP地址:32位(bit),4个字节,每一个字节为0~255之间的整数,及我们日常见到的IP地址格式。
目的IP地址:32位(bit),4个字节,每一个字节为0~255之间的整数,及我们日常见到的IP地址格式。
Option 选项 :是数据报中的一个可变长的可选信息。
选项字段以32bit 为界,不足时插入值为0填充字节。保证IP首部始终是 32bit 的整数倍。由于Delphi里面没有位域这个概念,所以定义结构的时候只能整字节了,挺怀恋C++或者Erlang的,有位域定义出来和使用起来都很方便了 。
//IP包
TIPHeader = packed record
iph_verlen: byte; // 版本和长度
iph_tos: byte; // 服务类型
iph_length: word; // 总长度,2个无符号字节所以只能65535
iph_id: word; // 标识
iph_offset: word; // 标志和片偏移
iph_ttl: byte; // 生存时间
iph_protocol: byte; // 协议
iph_xsum: word; // 头校验和
iph_src: longword; // 源地址
iph_dest: longword; // 目的地址
end;
这个结构体有什么用呢?其实在嗅探的时候就很有用了。
2、ICMP头和报文校验和的计算
//定义ICMP包头
typedef struct _ICMP_HEADER {
BYTE bType ; // 类型8bit
BYTE bCode ; // 代码8bit
USHORT nCheckSum ; // 校验和16bit
USHORT nId ; // 标识,本进程ID16bit
USHORT nSequence ; // 序列号16bit
UINT nTimeStamp ; // 可选项,这里为时间,用于计算时间32bit
} ICMP_HEADER, *PICMP_HEADER ;
送ICMP报文时,必须由程序自己计算校验和,将它填入ICMP头部对应的域中。校验和的计算方法是:
将数据以字(16位)为单位累加到一个双字中(强转换双字类型),如果数据长度为奇数(奇数个字节),最后一个字节将被扩展到字,累加的结果是一个双字,最后将这个双字的高16位和低16位相加后取反,便得到了校验和。
// 计算ICMP包校验值
// 参数1:ICMP包缓冲区
// 参数2:ICMP包长度
USHORT GetCheckSum ( LPBYTE lpBuf, DWORD dwSize )
{
DWORD dwCheckSum = 0 ;
USHORT* lpWord = (USHORT*)lpBuf ;
// 累加
while ( dwSize > 1 )
{
dwCheckSum += *lpWord++ ;
dwSize -= 2 ;
}
// 如果长度是奇数
if ( dwSize == 1 )
dwCheckSum += *((LPBYTE)lpWord) ;
// 高16位和低16位相加
dwCheckSum = ( dwCheckSum >> 16 ) + ( dwCheckSum & 0xFFFF ) ;
// 取反
return (USHORT)(~dwCheckSum ) ;
}
相关推荐
- 方差分析简介(方差分析通俗理解)
-
介绍方差分析(ANOVA,AnalysisofVariance)是一种广泛使用的统计方法,用于比较两个或多个组之间的均值。单因素方差分析是方差分析的一种变体,旨在检测三个或更多分类组的均值是否存在...
- 正如404页面所预示,猴子正成为断网元凶--吧嗒吧嗒真好吃
-
吧嗒吧嗒,绘图:MakiNaro你可以通过加热、冰冻、水淹、模塑、甚至压溃压力来使网络光缆硬化。但用猴子显然是不行的。光缆那新挤压成型的塑料外皮太尼玛诱人了,无法阻挡一场试吃盛宴的举行。印度政府正...
- Python数据可视化:箱线图多种库画法
-
概念箱线图通过数据的四分位数来展示数据的分布情况。例如:数据的中心位置,数据间的离散程度,是否有异常值等。把数据从小到大进行排列并等分成四份,第一分位数(Q1),第二分位数(Q2)和第三分位数(Q3)...
- 多组独立(完全随机设计)样本秩和检验的SPSS操作教程及结果解读
-
作者/风仕在上一期,我们已经讲完了两组独立样本秩和检验的SPSS操作教程及结果解读,这期开始讲多组独立样本秩和检验,我们主要从多组独立样本秩和检验介绍、两组独立样本秩和检验使用条件及案例的SPSS操作...
- 方差分析 in R语言 and Excel(方差分析r语言例题)
-
今天来写一篇实际中比较实用的分析方法,方差分析。通过方差分析,我们可以确定组别之间的差异是否超出了由于随机因素引起的差异范围。方差分析分为单因素方差分析和多因素方差分析,这一篇先介绍一下单因素方差分析...
- 可视化:前端数据可视化插件大盘点 图表/图谱/地图/关系图
-
前端数据可视化插件大盘点图表/图谱/地图/关系图全有在大数据时代,很多时候我们需要在网页中显示数据统计报表,从而能很直观地了解数据的走向,开发人员很多时候需要使用图表来表现一些数据。随着Web技术的...
- matplotlib 必知的 15 个图(matplotlib各种图)
-
施工专题,我已完成20篇,施工系列几乎覆盖Python完整技术栈,目标只总结实践中最实用的东西,直击问题本质,快速帮助读者们入门和进阶:1我的施工计划2数字专题3字符串专题4列表专题5流程控制专题6编...
- R ggplot2常用图表绘制指南(ggplot2绘制折线图)
-
ggplot2是R语言中强大的数据可视化包,基于“图形语法”(GrammarofGraphics),通过分层方式构建图表。以下是常用图表命令的详细指南,涵盖基本语法、常见图表类型及示例,适合...
- Python数据可视化:从Pandas基础到Seaborn高级应用
-
数据可视化是数据分析中不可或缺的一环,它能帮助我们直观理解数据模式和趋势。本文将全面介绍Python中最常用的三种可视化方法。Pandas内置绘图功能Pandas基于Matplotlib提供了简洁的绘...
- Python 数据可视化常用命令备忘录
-
本文提供了一个全面的Python数据可视化备忘单,适用于探索性数据分析(EDA)。该备忘单涵盖了单变量分析、双变量分析、多变量分析、时间序列分析、文本数据分析、可视化定制以及保存与显示等内容。所...
- 统计图的种类(统计图的种类及特点图片)
-
统计图是利用几何图形或具体事物的形象和地图等形式来表现社会经济现象数量特征和数量关系的图形。以下是几种常见的统计图类型及其适用场景:1.条形图(BarChart)条形图是用矩形条的高度或长度来表示...
- 实测,大模型谁更懂数据可视化?(数据可视化和可视化分析的主要模型)
-
大家好,我是Ai学习的老章看论文时,经常看到漂亮的图表,很多不知道是用什么工具绘制的,或者很想复刻类似图表。实测,大模型LaTeX公式识别,出乎预料前文,我用Kimi、Qwen-3-235B...
- 通过AI提示词让Deepseek快速生成各种类型的图表制作
-
在数据分析和可视化领域,图表是传达信息的重要工具。然而,传统图表制作往往需要专业的软件和一定的技术知识。本文将介绍如何通过AI提示词,利用Deepseek快速生成各种类型的图表,包括柱状图、折线图、饼...
- 数据可视化:解析箱线图(box plot)
-
箱线图/盒须图(boxplot)是数据分布的图形表示,由五个摘要组成:最小值、第一四分位数(25th百分位数)、中位数、第三四分位数(75th百分位数)和最大值。箱子代表四分位距(IQR)。IQR是...
- [seaborn] seaborn学习笔记1-箱形图Boxplot
-
1箱形图Boxplot(代码下载)Boxplot可能是最常见的图形类型之一。它能够很好表示数据中的分布规律。箱型图方框的末尾显示了上下四分位数。极线显示最高和最低值,不包括异常值。seaborn中...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- libcrypto.so (74)
- linux安装minio (74)
- ubuntuunzip (67)
- vscode使用技巧 (83)
- secure-file-priv (67)
- vue阻止冒泡 (67)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)