2013-05-30 3 views
4

У меня есть встроенное устройство, которое посылает мне дату UTC в этом формате (дата 4 байта):Кодирование декодирование байта

buffer.push_back((BYTE)(time_utc & 0x000000FF)); 
buffer.push_back((BYTE)((time_utc & 0x0000FF00) >> 8)); 
buffer.push_back((BYTE)((time_utc & 0x00FF0000) >> 16)); 
buffer.push_back((BYTE)((time_utc & 0xFF000000) >> 24)); 

На сервере я получаю байт и хранить их в socket_buf, начиная с индекса 0-3 и его расшифровка с помощью следующей логики

mypkt.dateTime = ((socket_buf[0] << 24) + 
(socket_buf[1 ] << 16) + socket_buf[2] << 8) + 
(socket_buf[3] << 0)); 

Но я не уверен, если я правильно его расшифровки, поскольку даты я не правильно. Может ли кто-нибудь предложить мне правильный способ его декодирования? Я декодирование даты с помощью команды Linux (16711840 этого число я получаю путем декодирования):

#date -d @16711840 
+0

обе машины являются конечными? –

+0

Я думаю, что это связано с порядком байтов в сетях. Сетевой порядок байтов является большим, и большинство процессоров Intel мало endian => это может быть ошибка. Вы посмотрели на функции C 'htons()' и 'ntohs()'? – jcxz

+0

Но я также отправляю другие данные, которые я собираюсь извлечь правильно, я больше согласен с моей логикой относительно того, что я правильно декодирую его из socket_buf. Я не уверен, что мне нужно делать это так же, как на устройстве. – Rohit

ответ

-3

ли вы очистить свой socket_buf?

Вы уверены, что ваш компьютер большой enddian?

Кроме того, я предлагаю вам использовать: или вместо оператора вместо оператора.

Это может сэкономить больше времени.

mypkt.dateTime = (long) ((socket_buf[0] << 24) | (socket_buf[1] << 16) | socket_buf[2] << 8) | (socket_buf[3] << 0)); 
+1

Код в исходном сообщении не зависит от конца. Побитовое ИЛИ эквивалентно добавлению. Не должно быть разницы в производительности с включенным оптимизатором (но в этом случае может быть проще читать и понимать). Кроме того, ваш предложенный метод не работает, если 'socket_buf' имеет неправильный целочисленный тип. И актеры, подписанные давно, бессмысленны и иррациональны. – Lundin

+0

Да, буфер сокета прозрачен. Lundin, так что вы хотите сказать, что мне не нужно делать & -инг, как это было в исходном коде с устройства. – Rohit

+0

Этот код работает отлично для меня: mypkt.dateTime = ((socket_buf [HB_PKT_DATE_TIME] << 0) + (socket_buf [HB_PKT_DATE_TIME +1] << 8) + (socket_buf [HB_PKT_DATE_TIME + 2] << 16) + (socket_buf [HB_PKT_DATE_TIME + 3] << 24)); – Rohit

8

Сочинения код немного младшие - это первая отправка младших байт.

Ваш код чтения ожидается big endian - он берет нулевой байт и сдвигает его на 24 бита.

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

Попробуйте это вместо:

mypkt.dateTime = ((socket_buf[0] << 0) + 
        (socket_buf[1] << 8) + 
        (socket_buf[2] << 16) + 
        ((uint32_t)socket_buf[3] << 24)); 

Бросок необходимо (но только на последнем смену), потому что 0x80 - 0xff будет преобразован в signed int и это не определено, что происходит с битами, которые сдвигаются в Значок бит (спасибо @Lundin)

NB: 16711840 не является «текущим» значением даты-времени в Unix, которое вы используете для его представления. У вас могут быть другие проблемы в другом месте.

0

Поскольку socket_buf объявлен unsigned char, socket_buf[0] << 24 является ошибкой.

socket_buf[0] is unsigned char и получит целочисленное значение, равное int. Независимо от того, является ли это 16 бит или 32 бита в этой конкретной системе, это не имеет значения, потому что программа будет нестабильной. В обоих случаях он заканчивается как подписанная переменная. Вы оставите сдвиг подписанной переменной и смените двоичные на знаковые биты. Тогда вы делаете дополнение на этом.

Правильный способ записи декодирования заключается в следующем:

mypkt.dateTime = (((uint32_t)socket_buf[0] << 24) | 
        ((uint32_t)socket_buf[1] << 16) | 
        ((uint32_t)socket_buf[2] << 8) | 
        ((uint32_t)socket_buf[3] << 0)); 

Кроме того, вы, кажется, изменить порядок следования байтов в обратном направлении между кодированием и декодированием. Я не совсем понимаю, что это значит с энтузиазмом, ваш код просто использует непоследовательный порядок между buffer по сравнению с sock_buf.

+0

уверен, что 'unsigned char' будет повышен до' _unsigned_ int'? И в любом случае это не приведет к сбою. – Alnitak

+0

ОК, уточнение - поскольку '0 - 0xff' оба помещаются внутри' int', это действительно будет повышаться до 'int', а не' uint', но это не вызовет расширение знака_. Результат 'int' будет по-прежнему иметь диапазон' 0 - 0xff'. – Alnitak

+1

@Alnitak Он будет переведен в int, _not_ в unsigned int (C11 6.3.1.1). И если int 32 бит, вы по существу получите этот код: 'int32_t my_int = 0xFF; my_int << 24; ', что является неопределенным поведением, согласно C11 6.5.7. – Lundin

Смежные вопросы