【进阶】"结构体嵌入共联体"在协议解析中的神操作!

2023-05-16

1、聊一聊

     " I was alone,but not lonely"!

     今天的文章话题引出来自bug技术交流群,主要是想把这种协议解析和设计的方式分享给大家!

2、正文部分

1

话题引出

  • bug技术交流群一个小哥贴出了如下图片 :

  • 问到了共联体类型强制转化的问题,当时bug菌点开看到这几行代码便产生了莫名的亲切感,或许这些就是C语言的魅力所在吧。

  • 其实这种操作在通信协议中拆包、解包是非常常见的,但是bug菌也是在参加工作以后在部门的代码中get到,所以这里整理分享给各位。

2

操作解析

    有认真阅读过bug公众号文章的小伙伴,应该在其他文章中也看到过这种操作,不过比较分散,今天抽出来再好好聊聊!

1

buff直接转结构体

  • 上图是简单的协议包,包括帧头,长度和数据部分,在通信数据接收或者发送末端其都位于字节流中,比如UART通信,最后都是放到Sendbuff[N]或者RecBuff[N],然后发送出去。

  • 如果你打包好了结构体,然后一个个填充byte到发送或者接受buff,着实有点麻烦,然而通过结构体指针强制类型转换为uint8_t *pSendBuff;然后在进行字节流发送,那就简洁很多了。

  • 当然在此过程中你还要注意字节序、对齐等等,在往期的文章中bug菌都有讲到,模拟此过程参考下面代码。

参考示例:

#include <stdio.h>
#include <stdlib.h>

#pragma pack(1)
typedef struct _tag_Pack
{
    int Head;
    int Len;
    char Data[2];
} sPack;

int main(int argc, char *argv[]) {
    sPack stSendPack;
    sPack *pstRevPack = NULL;
    unsigned char *SendBuff =NULL;
    unsigned char  RevBuff[20] ={0};
    int cnt = 0;

    //模拟封包 
    stSendPack.Head = 0xFF;
    stSendPack.Len = 0x08;
    stSendPack.Data[0] = 0x1;
    stSendPack.Data[1] = 0x2;

    //模拟发送包
    SendBuff = (unsigned char *)(&stSendPack);

    printf("SendData: ") ;
    for(cnt = 0 ;cnt < sizeof(sPack);cnt++)
    {
        printf("0x%02X  ",*(SendBuff + cnt)) ;
        RevBuff[cnt] = *(SendBuff + cnt);  //这里模拟接受到数据 
    } 

     printf("\n\n");
    //模拟解包 
     pstRevPack = (sPack *)RevBuff;
     printf("pstRevPack.Head    = 0x%X\n",pstRevPack->Head) ;
     printf("pstRevPack.Len     = 0x%X\n",pstRevPack->Len) ;
     printf("pstRevPack.Data[0] = 0x%X\n",pstRevPack->Data[0]) ;
     printf("pstRevPack.Data[1] = 0x%X\n",pstRevPack->Data[1]) ;

    printf("\n欢迎关注公众号:最后一个bug\n");
    return 0;
}

运行结果:

2

buff直接转结构共联体 

  • 上一节我们谈到了接受和发送的buff直接转结构体,然后进行解包处理,而交流群里面图片中是转共联体,可以说这样的数据结构结合是非常完美的。

  • buff转结构体类型,就必须buff字节流里的格式与结构体一致,才能正确的解析,而共联体是一种复合类型结构,可以存在多种形式的数据提取,这样就可以带来更多的灵活度,下面代码在操作一波。

参考示例:

#include <stdio.h>
#include <stdlib.h>

#pragma pack(1)
typedef struct _tag_PackType1
{
    int Head;
    int Len;
    char Data[2];
} sPackType1;

typedef struct _tag_PackType2
{
    int Head;
    int Len;
    int Data[2];
} sPackType2;

typedef struct _tag_PackType3
{
    int Head;
    int Len;
    float Data[2];
} sPackType3;

//结构共联体
typedef union _tag_PackType
{
    sPackType1 stPackType1;
    sPackType2 stPackType2;
    sPackType3 stPackType3;
} uPackType;

//不同结构体类型的解析函数
void ParsePackType1(uPackType *punPackType)
{
    punPackType->stPackType1.Head = 0xF1;
    //you do something! 
}

void ParsePackType2(uPackType *punPackType)
{
    punPackType->stPackType2.Head = 0xF2;
    //you do something! 
}

void ParsePackType3(uPackType *punPackType)
{
    punPackType->stPackType3.Head = 0xF3;
    //you do something! 
}
/******************************************
 * Fuction: Buff转结构共联体 
 * Author :(公众号:最后一个bug) 
 *****************************************/ 
int main(int argc, char *argv[]) {

    uPackType *punPackType;
    unsigned char  RevBuff[20] ={0};

    //通信字节流接受到 RevBuff以后强转 
    punPackType = (uPackType*)RevBuff;

    //根据自身需要,不同的解析函数,统一传递共联体即可 
    ParsePackType1(punPackType);
    ParsePackType2(punPackType);
    ParsePackType3(punPackType); 

    printf("\n欢迎关注公众号:最后一个bug\n");
    return 0;
}
  • 以上就是今天的全部内容,如果代码都不能讲清楚,那bug菌也没办法了,enjoy!

3、结束语

     下班回家就一直肝这篇文章,有点小累,作为一名原创作者真不容易,大家且看且珍惜。

    还有读者讨论由于之前是内测,现在系统收回改造,应该要等一些时日,所以本文没法留言了!

    好了,这里是公众号:“最后一个bug”,一个为大家打造的技术知识提升基地,如果你喜欢交流可以添加下方bug菌微信,我拉你加入公众号技术交流群。

推荐好文  点击蓝色字体即可跳转

☞【MCU】把"安卓HAL层思想"引到单片机软件开发中

☞【MCU】可怕,别人把我MCU固件给反汇编了!(逆向)

☞ 【MCU】寄存器、标准库、HAL库、LL库,这么多库!你叫我怎么选?

☞ 【嵌入式C】你有想过"数组下标"为何从0开始吗?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【进阶】"结构体嵌入共联体"在协议解析中的神操作! 的相关文章

  • C++/Java调用C++动态链接库————附带示例和详细讲解

    文章目录 0 准备1 C 43 43 调用动态链接库2 Java调用C 43 43 动态链接库3 运行 0 准备 在CMake中 xff0c 使用如下的方法把代码编译成动态 静态链接库 xff1a span class token comm
  • 什么变量存放在栈和堆

    内容会持续更新 xff0c 有错误的地方欢迎指正 xff0c 谢谢 什么是栈区 xff0c 什么是堆区 栈区 xff08 stack xff09 xff1a 由编译器自动分配释放 xff0c 存放函数的参数值 局部变量的值等 xff0c 内
  • C++改写Matlab源码实践二之【传递表格数据】————附带详细讲解和示例

    文章目录 0 背景1 Matlab有用代码提取2 转换为C 43 43 2 1 设定变量类型2 2 预先和定义声明变量 3 改写转换后的C 43 43 代码3 1 指定输入的文件3 2 改写处理 96 Data 96 和 96 Data1
  • Kylin4.0下载安装指南———附带详细安装过程

    文章目录 0 结果1 下载1 1 下载kylin1 2 下载spark1 3 jdk hadoop hive zookeeper安装1 4 Mysql安装 2 配置Mysql数据存储2 1 配置mysql2 2 配置Zookeeper2 3
  • 2023年的专业408算法题

    文章目录 0 结果1 题目2 思路3 实现附录 0 结果 1 题目 对于一个有向图 xff0c 如果一个顶点的出度大于入度 xff0c 则这个顶点称为K顶点 有向图用邻接矩阵存储 xff0c 数据结构定义如下 xff1a span clas
  • 专业408历年算题大全(2009~2023年)——附带详细代码和多种思路

    文章目录 1 题型总结1 1 线性表 xff08 6年 xff09 1 1 1 常用思想 1 2 链表 xff08 4年 xff09 1 2 1 常用思想 1 3 树 xff08 3年 xff09 1 3 1 常用思想 1 4 图 xff0
  • 2022年专业408算法题

    文章目录 0 结果1 题目2 思路3 实现3 1 思路一 xff08 中序遍历搜查搜索数 xff09 3 2 思路二 xff08 二叉搜索树的定义 xff09 附录 0 结果 1 题目 2 思路 1 xff0c 首先明确二叉搜索树的定义 x
  • 2021年专业408算法题

    文章目录 0 结果1 题目2 思路3 实现附录 0 结果 1 题目 2 思路 遍历邻接矩阵的每一行和列的非零元素的个数 xff0c 来统计每个顶点的度 xff08 出度和入度和 xff09 xff0c 并记录度为奇数的顶点个数 xff0c
  • jetbrains软件打开后突然闪退

    文章目录 0 背景1 错误重现2 错误原因3 解决方法 0 背景 在使用jetbrains编程软件时 xff0c 突然出现打开就闪退的情况 一开始还以为是系统升级到macOS13 1的原因 xff0c 经过查阅网上资料 xff0c 发现ma
  • 2011年专业408算法题

    文章目录 0 结果1 题目2 思路2 1 思路1 xff08 暴力解 xff1a 排序 xff09 2 2 思路2 xff08 较优解 xff1a 归并合并数组 xff09 2 3 思路3 xff08 较优解 xff1a 数组指针后移 xf
  • 2014年408专业算法题

    文章目录 0 结果1 题目2 思路附录 0 结果 1 题目 2 思路 二叉树的带权路径长度 xff08 WPL xff09 的计算方法有两种 xff1a 1 xff0c 定义 xff1a W P L 61
  • 2016年专业408算法题

    文章目录 0 结果1 题目2 思路2 1 思路1 xff08 较优解 xff1a 排序 xff09 2 2 思路2 xff08 最优解 xff1a 类快排思想排序 xff09 附录 0 结果 较优解 xff1a 最优解 xff1a 1 题目
  • 2017年408专业算法题

    文章目录 0 结果1 题目2 思路附录 0 结果 1 题目 2 思路 因为要转换为中序表达式 xff0c 因此使用中序遍历 在中序遍历的过程中 xff0c 对于当前访问的非空结点p xff0c 则先输出 34 xff0c 然后递归调用左子树
  • Python面向对象编程

    文章目录 1 作用域1 1 局部作用域 2 类成员权限3 是否继承新式类4 多重继承5 虚拟子类6 内省 在运行时确定对象类型的能力 7 函数参数8 生成器 1 作用域 1 1 局部作用域 1 xff0c 当局部变量遮盖全局变量 xff0c
  • 增大整数———晴问算法

    文章目录 1 题目2 思路3 代码 1 题目 2 思路 首先把数字n转化为字符串s xff0c 然后把第一个字符转换为数字得到正整数的首位 如果输入的数位a大于首位 xff0c 则把字符串s拼接在字符串化的数位后面形成新字符串ans xff
  • 从零开始开发物联网项目(6)——Arduino和ESP8266自动数据上传终端

    前面几节介绍了Mqtt协议以及用ESP8266模块作为客户端连接Mqtt服务器并实现数据的发布和订阅 这一节我们就正式的开始制作第一个物联网终端 xff0c 基于Arduino和ESP8266模块 之所以选择了Arduino是因为它的开发比
  • centos7无法上网问题

    项目场景 xff1a 在虚拟机VM中安装了centos7 xff0c 突然无法上网 xff0c 不知道咋回事 xff0c 所以上网查了资料博客 xff0c 现总结如下 一 首先打开虚拟的设置 xff0c 可以看到虚拟机网络的设置默认为NAT
  • centos安装jdk1.8

    Linux平台安装JDK的方式大致有三种 xff08 rpm yum 手动安装 xff0c 这里简单介绍手动安装JDK的方式 一 去Oracle官网下载所需JDK包 这里跟windows平台差不多 xff0c 去官网查找链接下载对应JDK安
  • 基本类型和包装类型的区别

    简介 Java 的每个基本类型都对应了一个包装类型 xff0c 比如说 int 的包装类型为 Integer xff0c double 的包装类型为 Double 基本类型和包装类型的区别主要有以下 4 点 区别 1 包装类型可以为 nul
  • IDEA System.out.println(“中文“);输出中文乱码问题

    问题描述 xff1a span class token class name System span span class token punctuation span out span class token punctuation sp

随机推荐

  • Error:(3, 39) java: 程序包com.alibaba.fastjson.annotation不存在

    问题描述 xff1a IDEA依赖包下载不全 xff0c 报错 xff1a Error 3 39 java 程序包com alibaba fastjson annotation不存在 解决方案 xff1a span class token
  • idea中module项目没有蓝色小方块问题

    问题描述 xff1a idea项目没有蓝色小方块问题 把项目中module删除之后重新添加 xff0c 发现项目右下角没有 34 蓝色小方块 34 xff0c maven也不能识别 xff0c 如下图 xff1a 解决方案 xff1a 打开
  • TCP通信聊天服务端和客户端(C/C++语言开发)附完整源码

    TCP通信源码 一 服务端源码二 客户端源码三 效果 距离上次学Python写的Python实现简单聊天室已经过去好久了 xff0c 现在学c 43 43 又写了一遍 xff0c 其实过程差不多 xff0c 无非是语法的变化 xff0c 目
  • 淘宝cp210X提示“VeriFone USB Modem”无法匹配驱动

    淘宝cp210X提示 VeriFone USB Modem 无法匹配驱动 前段时间 xff0c 在淘宝上买了cp210X usb转串口芯片 xff0c 安装 调试板驱动CP210x Windows Drivers xff08 0积分下载地址
  • 2021年 秋招面试记录

    2021年 春招面试记录 大华 大华一面 xff1a 7 13 list map set IOC AOP 单例模式 在哪使用 过滤 xff1f 提取数字 43 排序 大华二面 xff1a 7 27 mybatis缓存 二级缓存有什么问题 r
  • Java面试必背八股文[1]:Java 基础

    面向对象和面向过程的区别 面向过程 xff1a 面向过程是一种以事件为中心的编程思想 xff0c 编程的时候把解决问题的步骤分析出来 xff0c 然后用函数把这些步骤实现 xff0c 在一步一步的具体步骤中再按顺序调用函数 面向对象 xff
  • Java面试必背八股文[3]:Java 集合

    Java 集合框架图 String 为什么是不可变的 简单的来说 xff1a String 类中使用 final 关键字修饰字符数组来保存字符串 xff0c private final char value xff0c 所以 String
  • Java面试必背八股文[2]:Java 多线程

    简述线程 程序 进程的基本概念 xff1f 程序是含有指令和数据的文件 xff0c 被存储在磁盘或其他的数据存储设备中 xff0c 也就是说程序是静态的代码 进程是程序的一次执行过程 xff0c 是系统运行程序 资源分配 的基本单位 xff
  • Java面试必背八股文[4]:JVM相关

    什么是JMM模型 xff1f JMM并不真实存在 xff0c 只是一种规范 xff0c 通过这种规范来让定义程序中各个变量的访问方式 JVM运行程序的实体是线程 xff0c 而每个线程创建时JVM都会为其创建一个工作内存 有些地方称为栈空间
  • Java面试必背八股文[5]:MySQL

    Drop Delete TRUNCATE的区别 drop drop直接删掉表 xff1b drop语句将表所占用的空间全释放掉 drop语句将删除表的结构被依赖的约束 xff08 constrain xff0c 触发器 xff08 trig
  • Java面试必背八股文[6]:Redis

    使用 Redis 有哪些好处 xff1f 1 速度快 xff0c 因为数据存在内存中 xff0c 类似于 HashMap xff0c HashMap 的优势就是查找和操作的时间复杂度都是 O xff08 1 xff09 2 支持丰富数据类型
  • Java面试必背八股文[7]:Spring

    什么是 Spring Framework xff1f Spring 是一个开源应用框架 xff0c 旨在降低应用程序开发的复杂度 它是轻量级 松散耦合的 它具有分层体系结构 xff0c 允许用户选择组件 xff0c 同时还为 J2EE 应用
  • Java面试必背八股文[8]:MyBatis

    MyBatis Mybatis是一个优秀的持久层ORM框架 xff0c 它对jdbc的操作数据库的过程进行封装 xff0c 使得开发者只需要关注SQL本身 不需要花费精力去处理一些重复和繁琐的步骤 通过java对象和statement中的s
  • Java面试必背八股文[9]:SpringBoot

    什么是 Spring Boot xff1f Spring Boot 是由 Pivotal 团队提供的全新框架 xff0c 其设计目的是用来简化 Spring 应用的初始搭建以及开发过程 该框架使用了特定的方式来进行配置 xff0c 从而使开
  • SIP鉴权简介

    介绍 SIP提供了一个无状态 基于挑战的鉴权机制 xff0c 该机制基于HTTP的鉴权 任何时候一个UA或代理服务器收到一个请求 除CANCEL和ACK xff0c 都可以挑战请求的发起者要求其提供身份的保证 一旦发起者判定了身份 xff0
  • Java面试必背八股文[10]:RabbitMQ

    什么是 rabbitmq 采用 AMQP Advanced Message Queuing Protocol xff0c 高级消息队列协议 xff09 的一种消息队列技术 最大的特点就是消费并不需要确保提供方存在 xff0c 实现了服务之间
  • Java面试必背八股文[11]:计算机网络

    OSI与TCP IP各层的结构 xff1f 答 OSI分层 xff08 7层 xff09 xff1a 物理层 数据链路层 网络层 传输层 会话层 表示层 应用层 TCP IP分层 xff08 4层 xff09 xff1a 网络接口层 网际层
  • Java面试必背八股文[12]:计算机操作系统

    进程和线程有什么区别 xff1f 进程 xff08 Process xff09 是系统进行资源分配和调度的基本单位 xff0c 线程 xff08 Thread xff09 是CPU调度和分派的基本单位 xff1b 线程依赖于进程而存在 xf
  • 2022年总结

    2022年总结 人生的转折痛并快乐着愿岁月静好未来加油吧 人生的转折 2022年 人生的转折点了 xff0c 研究生毕业 xff0c 再也没有了那个 学生 的身份 xff0c 新的篇章 xff0c 如何续写 xff1f 2022年6月20日
  • 【进阶】"结构体嵌入共联体"在协议解析中的神操作!

    1 聊一聊 34 I was alone but not lonely 34 今天的文章话题引出来自bug技术交流群 xff0c 主要是想把这种协议解析和设计的方式分享给大家 xff01 2 正文部分 1 话题引出 bug技术交流群一个小哥