У меня есть структура, которую я отправляю на сокет UDP:
typedef struct
{
char field_id;
short field_length;
char* field;
} field_t, *field_p;
Я могу читать field_id
и field_length
после того, как полученный на серверной стороне UDP, однако указатель на field
недопустимо как ожидалось.
Что лучший метод должен правильно отправить и получить динамический символ*?
У меня есть основное использование решения memcpy
на стороне клиента:
char* data =
(char*)malloc(sizeof(field_t) + (sizeof(char) * strlen(my_field->field)));
memcpy(data, my_field, sizeof(field_t));
memcpy(data+sizeof(field_t), my_field->field, strlen(my_field->field) + 1);
И на стороне сервера:
field_p data = (field_p)buffer;
field_string = (char*)buffer+sizeof(field_t);
Существует ли более чистый способ сделать это, или действительно ли это - единственный путь?
Спасибо.
Вы, конечно, не можете отправить указатель через сокет - избавьтесь от поля char *;
. Вместо этого просто добавьте пару идентификаторов и размеров к самим данным. Используйте writev (2)
или sendmsg (2)
, чтобы избежать перемещения данных из буфера в буфер.
Следите за выравниванием и заполнением элементов структуры и порядком следования байтов .
Определите вашу структуру как:
typedef struct
{
uint8_t field_id;
uint16_t field_length;
char field[0]; // note: in C99 you could use char field[];
} field_t, *field_p;
Тогда текстовый буфер будет немедленно следовать за вашей структурой. Просто запомните несколько уловок:
// initialize structure
field_t *
field_init (uint8_t id, uint16_t len, const char *txt)
{
field_t *f = malloc (sizeof (field_t + len)); // note "+ len";
f->field_id = id;
f->field_length = len;
memcpy (f->field, txt, len);
return f;
}
// send structure
int
field_send (field_t *f, int fd)
{
return write (fd, f, sizeof (*f) + f->field_length); // note "+ f->field_length"
}
Я не думаю, что это стандартно. Однако большинство компиляторов (GCC && MSVC) должны это поддерживать. Если ваш компилятор не поддерживает массив нулевого размера, вы можете использовать одноэлементный массив char - просто не забудьте вычесть лишний один байт при вычислении размера пакета.