Кодирование декодирование байт


У меня есть встроенное устройство, которое посылает мне дату 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
3 4

3 ответа:

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

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

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

Это может сэкономить вам больше времени.
mypkt.dateTime = (long) ( ( socket_buf[0] << 24) |  (socket_buf[1] << 16) |  socket_buf[2] << 8) | (socket_buf[3] << 0));

Код записиlittle endian - он посылает наименее значимый байт первым.

Ваш код чтения ожидает 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, какую бы конечность вы ни использовали для его представления. У вас могут быть другие проблемы в другом месте.

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

socket_buf[0] является 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) );

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