#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 #.
Удачи!