Порядок байтов и сокетов в C - PullRequest
7 голосов
/ 25 марта 2012

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

recvfrom(int socket, char *buffer, size_t length, int flags,
             struct sockaddr *address, socklen_t *address_len);

Затем я приводил буфер непосредственно к структуре и использовал ntohsи ntohl, чтобы изменить порядок байтов, например:

struct A * a = (struct A *)buffer;
Struct A b;
b.v1 = ntohs(a->v1);
b.v2 = ntohl(a->v2);

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

Я не контролирую отправителя.Отправитель находится в сетевом порядке байтов.Мой вопрос только в том, что: - Безопасно ли приводить буфер к структуре, а затем использовать ntohs и ntohl в этой приведенной структуре, чтобы создать реплику порядка хост-байтов этой структуры?Это самый быстрый подход?Если нет, то какой может быть самый быстрый подход?

1 Ответ

3 голосов
/ 25 марта 2012

Прежде всего, поскольку a является апоинтером, ваш код должен как минимум сделать это ...

b.v1 = ntohs(a->v1);
b.v2 = ntohl(a->v2);

Во-вторых, ответ зависит от обстоятельств и технических характеристик монитора пациента. Кто пишет код для монитора пациента? Есть ли спецификация для этого? Какую архитектуру машины он использует (если вы знаете), имеете ли вы дело только с одной моделью или существует много версий монитора - можете ли вы заменить монитор и т. Д. И т. Д.

Я собираюсь предположить, что вы не можете сменить монитор и что порядок байтов где-то задокументирован - и вам может придется создать свои собственные процедуры распаковки / упаковки, выполнение байтовой адресации и манипулирование битами - если только вы не знаете, что формат точно совпадает с форматом «сетевого» порядка, и что заполнение структур одинаково в сетевом буфере.

Так что-то вроде;

void unpack(struct *b, unsigned char *buffer)
{
   b->v1 = (buffer[0] <<8)|(buffer[1]);   
   b->v2 = (buffer[2] <<24)|(buffer[3] <<16)|(buffer[4] <<8)|(buffer[5]);
   etc....
}   

или как это, если вы предпочитаете ntohX;

void unpack(struct *b, unsigned char *buffer)
{
   b->v1 = ntohs(buffer+0);   
   b->v2 = ntohl(buffer+2);
   etc....
}   

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

...