简体   繁体   English

C#中C结构体字节流的序列化/反序列化策略

[英]Serialization/Deserialization strategy for byte stream of C structs in C#

I'm working on a Client app, written in C#, which should communicate with a legacy app (let's call it a server).我正在开发一个用 C# 编写的客户端应用程序,它应该与遗留应用程序进行通信(我们称之为服务器)。 The problem is that the server's API is represented as a bunch of plain old C structs.问题是服务器的 API 被表示为一堆普通的旧 C 结构。 Every struct has a 4-byte header and the data that follows it.每个结构体都有一个 4 字节的标头和它后面的数据。 It's just a byte stream.它只是一个字节流。

I understand that this particular binary format is unique (given by the legacy server app).我知道这种特殊的二进制格式是独一无二的(由旧服务器应用程序提供)。 Because of that, it's not possible to use any SerDes libraries like Protocol Buffers, which uses its way of encoding binary data.因此,不可能使用任何 SerDes 库,例如 Protocol Buffers,它使用其编码二进制数据的方式。

  • Is there any project/library for binary serialization that allows me to specify the type of message (like protobuff does) and its binary format?是否有任何用于二进制序列化的项目/库允许我指定消息类型(如 protobuff 那样)及其二进制格式? Every library I've seen was based either on JSON, XML, or proprietary binary format.我见过的每个库都基于 JSON、XML 或专有的二进制格式。
  • Suppose I would decide to write my own SerDes library (in C#).假设我决定编写自己的 SerDes 库(用 C#)。 What would be the best/recommended strategy for doing this?这样做的最佳/推荐策略是什么? I want to do it the professional way, at least once in my life.我想以专业的方式做这件事,至少在我的生活中一次。 Thanks!谢谢!

PS: We're talking about little-endian only. PS:我们只讨论小端。

This is how the server defines a message:这是服务器定义消息的方式:

struct Message1
{
    byte    Size;       // Header 1st byte
    byte    Type;       
    byte    ReqI;       
    byte    Zero;       //Header 4th byte.

    word    UDPPort;    // Actual data starts here.
    word    Flags;      

    byte    Sp0;        
    byte    Prefix;     
    word    Interval;   

    char    Admin[16];  
    char    IName[16];  
};

It sounds like you have fixed sized c structs being sent via a socket connection and you need to interpret those into handy C# classes.听起来您已经通过套接字连接发送了固定大小的 c 结构,您需要将它们解释为方便的 C# 类。

The easiest way may be to do all the message handling in code written in managed C++.最简单的方法可能是在用托管 C++ 编写的代码中完成所有消息处理。 In that you'd have a structure that, possibly with a bunch of pragmas, I'm sure could be made to have the same memory layout as the structure being sent through the socket.因为你有一个结构,可能有一堆编译指示,我确定可以使结构与通过套接字发送的结构具有相同的内存布局。 You would then also define a similar managed c++ class (eg containing managed strings instead of char arrays).然后,您还将定义一个类似的托管 C++ 类(例如,包含托管字符串而不是字符数组)。 You would also write code that converts the struct field by field into one of these managed classes.您还将编写代码,将结构字段逐个字段转换为这些托管类之一。 Wrap the whole thing up in a DLL, and include it in your C# project as a dependency.将整个内容包装在一个 DLL 中,并将其作为依赖项包含在您的 C# 项目中。

The reason for this is because managed C++, weird though it is as a language, is a far easier bridge between unmanaged and managed code and data structures.这样做的原因是因为托管 C++,虽然它作为一种语言很奇怪,但它是非托管和托管代码和数据结构之间更容易的桥梁。 There's no need to marshall anything, this is done for you.没有必要编组任何东西,这是为您完成的。 I've used his route to create libraries that make calls into Windows' hardware discovery facilities, for which there isn't (or wasn't) any pre-existing C# library.我使用他的方法创建了调用 Windows 硬件发现工具的库,其中没有(或没有)任何预先存在的 C# 库。 Using managed C++ code to call the necessary win32 functions was far easier than doing the same thing from C#.使用托管 C++ 代码调用必要的 win32 函数比在 C# 中执行相同的操作要容易得多。

Good luck!祝你好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM