Преобразование 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;
на другом конце выполните преобразование противоположным образом