C#解析字节序列中动态大小结构体的实现方案问询
C# 动态长度网络流数据包解析实现方案咨询
背景
当前正在开展网络流数据包解析相关开发工作,发送端逻辑已全部实现,仅负责客户端侧开发,需要严格按照数据原始格式完成解析。
此前所有数据包均为固定长度,采用结构体指针直接映射内存缓冲区的方案实现,代码如下:
[StructLayout(LayoutKind.Sequential, Pack = 1)] public unsafe ref struct MyConstSizedStruct { // 示例结构体 public uint Data1; public byte Data2; public fixed byte Version[6]; }
上述固定大小结构体总长度为 4 + 1 + 6 = 11 字节,接收到的数据存入缓冲区后,直接通过指针映射的方式将缓冲区数据转为结构体实例,实现代码如下:
public unsafe void HandleMyConstSizedStruct(ushort length, byte[] data) { MyConstSizedStruct pkt; fixed (byte* ptr = &data[0]) pkt = *(MyConstSizedStruct*)ptr; // 后续数据处理逻辑 }
该方案在固定大小结构体场景下运行稳定、性能优异。
当前遇到的问题
目前遇到动态大小结构体解析场景,待解析结构体原始定义如下:
[StructLayout(LayoutKind.Sequential, Pack = 1)] public unsafe struct MyDynamicSizedStruct { public uint Data1; public uint Data2; // 该位置为长度未知的空终止UTF-8字符串 public char* User; public uint Data3; public uint Data4; public byte Data5; public byte[] RestOfData; }
该类数据包总长度由网络报文前缀的ushort类型字段标识,但无法通过简单的指针强转完成解析,核心原因有两点:
- 结构体中包含长度未知的空终止UTF-8字符串
- 成员
byte[]属于托管类型,会导致整个结构体被识别为托管结构体,无法执行非托管指针强转操作
咨询是否存在优雅的方案实现该类结构体的解析,还是针对该特殊场景必须使用BinaryReader逐字段读取?
初步实现思路
目前已梳理的初步实现方向如下:
char*类型的User字段偏移固定为8字节,可从偏移8字节位置开始查找0x00终止字节,以此计算字符串缓冲区的长度- 考虑是否可以将
char*替换为Span<char>,在结构体中标识该缓冲区的长度;或是通过指针赋值,根据计算得到的偏移量调整后续Data3等字段的读取位置 - 确定字符串缓冲区的正确长度后,剩余的
RestOfData字节数组读取不存在障碍:由于已知报文总长度,可通过totalsize - 17 /*所有定长DataX字段的总大小*/ - /*User字符串实际占用长度*/计算得到该字节数组的长度
内容的提问来源于stack exchange,提问作者SelfishCrawler
相关产品推荐
相关产品推荐

