Отправка динамических массивов в структуре через UDP в C - PullRequest
0 голосов
/ 23 января 2019

Я работаю над кодом, в котором у меня есть структура, одним из ее членов является динамический массив (размер неизвестен до времени выполнения). Мне нужно отправить эту структуру через соединение UDP и иметь возможность читать и обрабатывать данные на другом конце.

Я знаю, что могу использовать указатель и malloc для определения динамического массива, но я не могу отправить указатель по UDP. и я тоже пытаюсь избежать сериализации.

структура выглядит примерно так: пользователь должен ввести идентификатор для определения типа сообщения, а также сообщения в массиве.

struct foo
{
    unsigned int ID;
    unsigned int Num;
    unsigned int size;
    char arr[size]; //I know this is not acceptable in C, just typing to show my question.
};

Есть ли другой способ создания динамического массива, который можно отправить через сокет UDP? и как лучше всего справиться с этим на принимающей стороне?

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Нет ничего особенного в отправке структур с динамическим размером по UDP.Как правило, вам просто нужно выделить достаточно памяти, как Бодо описал в своем ответе.Также посмотрите руководство GCC: Массивы нулевой длины и Массивы переменной длины , надеюсь, это поможет.И не забывайте, что размер сообщений UDP ограничен.

[...] Я также стараюсь избегать сериализации.

Я регулярно вижу людейизбегая кодеков, потому что они стремятся к хорошей производительности.В конце концов, они получают противоположное из-за проблем с перестановкой и упаковкой.Сериализация - ваш друг, особенно когда вы общаетесь с другими процессами.Стоит прочитать статью Роба Пайка о порядке следования байтов

0 голосов
/ 23 января 2019

Вы можете определить структуру с минимальным массивом и выделить память для структуры с большим массивом.

Следующий пример кода не является допустимым C, он неполный.Он также не обрабатывает возможные различия в байтовом порядке или размерах значений int при отправке по сети на другой компьютер.

struct foo
{
    unsigned int ID;
    unsigned int Num;
    unsigned int size;
    char arr[1];
};

int size = 123;

int i;
int ret;

struct foo *ptr = malloc(offsetof(struct foo, arr) + size);

ptr->ID = 42;
ptr->Num = 99;
ptr->size = size;
for(i=0; i<ptr->size; i++)
{
     ptr->arr[i] = data;
}


ret = sendto(sockfd, ptr, offsetof(struct foo, arr) + size, flags,
           dest_addr, addrlen);

Компилятору все равно, что вы получаете доступ к индексу массива большечем то, что вы определили в объявлении структуры.Вы должны проверить индекс в своем коде, чтобы избежать ошибок доступа к памяти.

Получатель может использовать recvfrom() с MSG_PEEK и размер заголовка (offsetof(struct foo, arr)) во временной структуре struct foo tmp;сначала выделите память в соответствии с полем size, затем прочитайте полный размер структуры в динамически выделенную память.См. Также Как прочитать пакет UDP с переменной длиной в C

Или использовать фиксированный буфер максимального размера для recvfrom(), а затем скопировать данные в динамически распределенную структуру.Возвращаемое значение recvfrom() сообщит вам необходимый размер.

Редактируйте в соответствии с предложениями в ответе Матиаса Саймона:

Если ваш компилятор поддерживает массивы нулевого размера,код можно немного упростить.

В определении структуры вы можете использовать char arr[0]; вместо char arr[1];.Это позволяет использовать sizeof struct foo вместо offsetof(struct foo, arr) в malloc(), sendto() и в recvfrom() с MSG_PEEK.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...