Преобразование uint16 t в char[2] для отправки через сокет (unix)

Я знаю, что есть вещи, примерно на этом.. Но мои мозги болят, и я не могу найти ничего, чтобы это сработало...

Я пытаюсь отправить 16-битное целое число без знака через сокет unix.. Для этого мне нужно преобразовать uint16_t в два символа, затем мне нужно прочитать их на другом конце соединения и преобразовать его обратно в unsigned int или uint16_t, в этот момент не имеет значения, использует ли он 2bytes или 4bytes (я запускаю 64bit, поэтому я не удается использовать unsigned int:)

Я делаю это в C btw

спасибо

4 ответов


почему бы просто не разбить его на байты с помощью mask и shift?

 uint16_t value = 12345;
 char lo = value & 0xFF;
 char hi = value >> 8;

(редактировать)

на другом конце, вы собираете с обратным:

 uint16_t value = lo | uint16_t(hi) << 8;

С верхней части моей головы, не уверен, что бросок не требуется.


char* pUint16 = (char*)&u16;

ie бросил адрес uint16_t.

char c16[2];
uint16_t ui16 = 0xdead;
memcpy( c16, ui16, 2 );

c16 теперь содержит 2 байта u16. В дальнем конце вы можете просто повернуть процесс вспять.

char* pC16 = /*blah*/
uint16_t ui16;
memcpy( &ui16, pC16, 2 );

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

как Steven sudt указывает, вы можете получить проблемы с big-endian-ness. чтобы обойти это, вы можете использовать htons (Host-to-network short) функция.

uint16_t ui16correct = htons( 0xdead );

и на дальнем конце используйте ntohs (сеть-хост короткий)

uint16_t ui16correct = ntohs( ui16 );

на машине little-endian это преобразует короткий в big-endian, а затем в дальнем конце преобразует обратно из big-endian. На машине big-endian 2 функции ничего не делают.

конечно, если вы знаю что архитектура обеих машин в сети использует одну и ту же конечность, тогда вы можете избежать этого шага.

посмотрите вверх ntohl и htonl для обработки 32-разрядных целых чисел. Большинство платформ также поддерживают ntohll и htonll для 64-бит.


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

разделить 16-разрядное число на два 8-разрядных чисел:

  • вы маскируете нижние 8 бит с помощью побитового оператора AND (&in C), чтобы верхние 8 бит стали 0, а затем назначаете этот результат одному символу.
  • вы сдвигаете верхние 8 бит вправо, используя правый оператор сдвига (>>в C), так что нижние 8 бит выталкиваются из целого числа, оставляя только верхние 8 бит и назначьте это другому символу.

затем, когда вы отправляете эти два символа по соединению, вы делаете обратное: вы сдвигаете то, что раньше было верхними 8 битами влево на 8 бит, а затем используете побитовое или объединяете это с другими 8 битами.


в основном вы отправляете 2 байта через сокет, это все, что сокет должен знать, независимо от endianness, signedness и так далее... просто разложите uint16 на 2 байта и отправьте их через сокет.

char byte0 = u16 & 0xFF;
char byte1 = u16 >> 8;

на другом конце выполните преобразование противоположным образом