Стратегия сериализации / десериализации для потока байтов структур C в C#

#c# #serialization #deserialization #protocol-buffers #marshalling

#c# #сериализация #десериализация #протокол-буферы #сортировка

Вопрос:

Я работаю над клиентским приложением, написанным на C #, которое должно взаимодействовать с устаревшим приложением (назовем его сервером). Проблема в том, что API сервера представлен в виде набора простых старых структур C. Каждая структура имеет 4-байтовый заголовок и следующие за ним данные. Это просто поток байтов.

Я понимаю, что этот конкретный двоичный формат уникален (задается устаревшим серверным приложением). Из-за этого невозможно использовать какие-либо библиотеки SerDes, такие как буферы протокола, которые используют свой способ кодирования двоичных данных.

  • Существует ли какой-либо проект / библиотека для двоичной сериализации, которая позволяет мне указывать тип сообщения (например, protobuff) и его двоичный формат? Каждая библиотека, которую я видел, была основана либо на JSON, XML, либо на собственном двоичном формате.
  • Предположим, я решил бы написать свою собственную библиотеку SerDes (на C #). Какая была бы лучшая / рекомендуемая стратегия для этого? Я хочу сделать это профессионально, хотя бы раз в жизни. Спасибо!

PS: Мы говорим только о младшем конце.

Так сервер определяет сообщение:

 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];  
};
  

Комментарии:

1. Мне непонятно, как приложение C # будет взаимодействовать с устаревшим приложением. Если устаревшее приложение представляет собой неуправляемый код, вам следует ознакомиться с маршалингом, взаимодействием и вызовом платформы. Если устаревшее приложение является управляемым кодом, оно должно быть намного проще в общении.

2. Устаревшее приложение представляет собой неуправляемый код (он написан на чистом C). Связь между клиентом и сервером осуществляется с использованием стандартного сокет-соединения.

3. Ну, таким образом, нет места для сериализации. Вы должны прочитать байты из сетевого потока и проанализировать соответствующую документацию. Сериализация, как я понял, представляет собой двухэтапный процесс. Данные сериализуются на одном конце, передаются некоторым носителем и десериализуются на другом конце для воссоздания исходного состояния.

4. Совет: вы можете создавать структуры на C # с явной компоновкой, которая точно имитирует код C (см. «Фиксированные буферы» для последних нескольких полей); затем вы можете использовать spans и MemoeyMarshal.Cast и boom: ввод байта [], вывод типизированных данных

Ответ №1:

Похоже, что у вас есть структуры c фиксированного размера, отправляемые через сокет-соединение, и вам нужно интерпретировать их в удобные классы C #.

Самым простым способом может быть выполнение всей обработки сообщений в коде, написанном на управляемом C . В этом случае у вас будет структура, которая, возможно, с кучей прагм, я уверен, может иметь тот же макет памяти, что и структура, отправляемая через сокет. Затем вы также должны определить аналогичный управляемый класс c (например, содержащий управляемые строки вместо массивов символов). Вы также должны написать код, который преобразует структуру поле за полем в один из этих управляемых классов. Оберните все это в DLL и включите его в свой проект C # в качестве зависимости.

Причина этого в том, что управляемый C , каким бы странным он ни был как язык, является гораздо более простым мостом между неуправляемым и управляемым кодом и структурами данных. Нет необходимости что-либо маршалировать, это делается за вас. Я использовал его маршрут для создания библиотек, которые выполняют вызовы средств обнаружения оборудования Windows, для которых нет (или не было) какой-либо ранее существовавшей библиотеки C #. Использовать управляемый код C для вызова необходимых функций win32 было намного проще, чем делать то же самое из C #.

Удачи!