在开发上位机的经历中,会有很多需要和下位机交互通信的场景,大多数都会定义一个和硬件的通信协议,最终在上位机代码中的形式其实就是符合通信协议的字节数组。

场景

在控制一些车辆进行货物搬运的业务场景下,我们需要即时的获取小车的状态数据,并且做出解析,最后进行业务处理。不管与下位机是如何通信的,最终都会读取到一个字节数组在内存中。

以TCP通讯为例子,一般会在通讯协议的报文头中定义报文的长度,从而解决一些通讯问题,如粘包等,最后读取到正文部分。

如何解析字节数组到类或结构体中

建立与通信协议一致的结构体

比如通讯协议的正文格式定义如下:

id motor_steps speed
1字节 2字节 1字节
  1. id 小车编号
  2. motor_steps 小车行走累计马达步数
  3. speed 小车当前速度

在代码中建立对应的结构体

[StructLayout(LayoutKind.Explicit)]
public struct VehicleStatus
{
[FieldOffset(0)] public byte id;
[FieldOffset(1)] public ushort motor_steps;
[FieldOffset(3)] public byte speed;
}
使用不安全代码将字节数组映射到结构体中
byte[] metaData = new byte[4] { 10, 88, 89, 5 }; //模拟一段报文
unsafe
{
fixed (byte* metaPointer = metaData)
{
VehicleStatus* status = (VehicleStatus*)metaPointer; Console.WriteLine($"小车编号:{status->id}");
Console.WriteLine($"小车速度:{status->speed}");
Console.WriteLine($"小车马达步数:{status->motor_steps}");
}
}

代码解释

StructLayout

表示某个类或者结构体里的成员的排列方式,这里我们使用LayoutKind.Explicit精确模式,该模式必须配合FieldOffset属性一起制定字段的物理内存排列位置。

fixed

用来钉住可移动变量,确保GC在执行期间对不会重新定位或释放包含对象实例,如果位置变了或者被释放了,谁还管你的非托管的指针对象呢?这边字节数组肯定是一个可移动变量了。

参考文档:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code#fixed-and-moveable-variables

c#优雅高效的读取字节数组——不安全代码(1)的更多相关文章

  1. 使用 mina 传输大字节数组

    转载自:http://seara520.blog.163.com/blog/static/16812769820103214817781/ 使用mina传输超过2k以上的数据时(采用tcp方式,如果是 ...

  2. JAVA IO分析二:字节数组流、基本数据&对象类型的数据流、打印流

    上一节,我们分析了常见的节点流(FileInputStream/FileOutputStream  FileReader/FileWrite)和常见的处理流(BufferedInputStream/B ...

  3. java 读取文件的字节数组

    /*文件64位编码*/ public static void main(String[] args) {    byte[] fileByte = toByteArray(newFile);   St ...

  4. Java基础知识强化之IO流笔记27:FileInputStream读取数据一次一个字节数组byte[ ]

    1. FileInputStream读取数据一次一个字节数组byte[ ]  使用FileInputStream一次读取一个字节数组: int read(byte[]  b) 返回值:返回值其实是实际 ...

  5. byte字节的输入流 建议使用字节数组形式接受内容 因为当输入流是汉字时候 会超出字节的范围 出现无法读取的现象

    byte字节的输入流 建议使用字节数组形式接受内容 因为当输入流是汉字时候 会超出字节的范围 出现无法读取的现象

  6. IO流处理文件读取到字节数组,再从字节数组读取到文件,Java实现

    package cn.zhang.io; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; impo ...

  7. Java将文件转为字节数组

    Java将文件转为字节数组 关键字:文件,文件流,字节流,字节数组,二进制 摘要:最近工作中碰到的需求是,利用http传输二进制数据到服务器对应接口,需要传输userId, file(加密后)等一系列 ...

  8. 【.net】从比较两个字节数组谈起

    上午,有位初学者朋友问:如何比较两个字节数组中各字节是否相等? 不许笑,我一向反对嘲笑初学者,初学者不认真学习时你可以批评,但不能讥嘲.你不妨想想,你自己开始学习编程的时候又是什么个光景? 好,于是, ...

  9. Java:IO流其他类(字节数组流、字符数组流、数据流、打印流、Properities、对象流、管道流、随机访问、序列流、字符串读写流)

    一.字节数组流: 类 ByteArrayInputStream:在构造函数的时候,需要接受数据源,而且数据源是一个字节数组. 包含一个内部缓冲区,该缓冲区包含从流中读取的字节.内部计数器跟踪 read ...

  10. mina 字节数组编解码器的写法 II

    I 里面的写法不够严谨,这也是我之前说它简陋的主要原因,下面来个更加严谨.完整一点儿的: ByteArrayEncoder.java package org.bruce.mina.cpp.codec; ...

随机推荐

  1. 2020 ccpc秦皇岛 赛后总结!!!!

    amazing!!!! 金牌!!!!! 总结一下这次的发挥,以及如何冲到了金牌. 1 有队友单开了银牌题,50分钟过了K题,当时只有5个人过K.他敲的过程中另个队友想出来另外一题的思路,等过了K,我直 ...

  2. Redis 线程模型

    一.概述 [1]Redis 是基于 Reactor 模式开发的网络事件处理器:这个处理器被称为文件事件处理器(file event handler),这个文件事件处理器是单线程的,所以 Redis 才 ...

  3. 用Python基于Google Bard做一个交互式的聊天机器人

    用Python基于Google Bard做一个交互式的聊天机器人 之前已经通过浏览器试过了 Google Bard ,更多细节请看: Try out Google Bard, Will Google ...

  4. 选择KV数据库最重要的是什么

    本文分享自华为云社区<选择KV数据库最重要的是什么?>,作者:GaussDB 数据库 . 经常有客户提到KV数据库,但却偏偏"不要Redis".比如有个做安全威胁分析平 ...

  5. 总结workerman启动与停止相关命令

    手册:https://www.workerman.net/doc/workerman/install/start-and-stop.html 本篇文章给大家介绍一下workerman启动与停止相关命令 ...

  6. 借AI之势,打破创意与想象的边界

    不要做这个时代的最后一只恐龙. IMMENSE.36氪|作者 1811年11月,英国,诺丁汉市西北一处小镇里,一群愤怒的纺织工人挥舞着锤头与斧子,一窝蜂地冲进车间里,将几台机器砸得粉碎. 后来,这场运 ...

  7. CTF-RE-学习记录-汇编

    八进制运算 加法表 1+1=2 1+2=3 2+2=4 1+3=4 2+3=5 3+3=6 1+4=5 2+4=6 3+4=7 4+4=10 1+5=6 2+5=7 3+5=8 4+5=11 5+5= ...

  8. 基于开源的 ChatGPT Web UI 项目,快速构建属于自己的 ChatGPT 站点

    作为一个技术博主,了不起比较喜欢各种折腾,之前给大家介绍过 ChatGPT 接入微信,钉钉和知识星球(如果没看过的可以翻翻前面的文章),最近再看开源项目的时候,发现了一个 ChatGPT Web UI ...

  9. .net core基于HttpClient实现的网络请求库

    Soda.Http 基于HttpClient封装的 Http 请求库.如果有什么好想法,可以提 Issue 或者 Pr.,如果想要使用,直接在nuget搜索Soda.Http即可. Github项目地 ...

  10. selenium验证码处理-获取验证码图片二进流数据转成原图保存

    1.因为视频的作者给的代码不完整,只有核心部分的代码. 2.视频作者示例使用的第三方破解12306的脚本网页(失效了) 所以本人无法复现,此次截取部分代码作为理解核心意思(思想方法最重要) 1.面向对 ...