Предыдущая | Оглавление | Следующая |
Преобразовать многобайтовые числа в системный или сетевой порядок байт
#include <netinet/in.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
Чтобы совсем испортить тебе жизнь, разные компьютеры используют разный порядок байт для внутреннего представления многобайтовых чисел (т.е. целых чисел, больших, чем char.) Проблема в том, что если ты перешлешь двухбайтовый short int с компьютера Intel на Mac (в смысле, пока Apple не стали применять процессоры Intel), то число, что один считает 1, другой поймет как 256, и наоборот.
Решение этой проблемы: все споры были забыты, люди решили, что Motorola и IBM все сделали правильно, а в Intel что-то напутали, и теперь в сети все числа передаются в формате "big-endian". Поскольку Intel применяет формат "little-endian", то политкорректно было назвать "big-endian" просто "Сетевым порядком байт". А эти функции преобразовывают числа из местного, системного порядка в сетевой, и наоборот.
(Это значит, что на машине Intel эти функции разворачивают порядок байт, а на PowerPC они ничего не делают, так как байты и так в Сетевом порядке. Но их все равно нужно использовать, чтобы сделать код переносимым на платформу Intel.)
Типы данных, которые нужно переворачивать, это 32-битное целое (как правило, int) и 16-битное целое ( как правило, short). 64-битные машины могут иметь и htonll() для 64-битных целых, но я ни разу такого не видел. Возможно, такую функцию нужно писать вручную.
В общем, эти функции работают так: сначала ты решаешь откуда преобразуешь число. Если из системного порядка ("host"), первая буква имени "h". Иначе - "n" ("network"). Дальше - "to" ("в"), потом буква, показывающая, куда ты преобразуешь, и последняя буква указывает тип данных, "s" (short) или "l" (long=int). Таким образом:
htons() |
host to network short |
htonl() |
host to network long |
ntohs() |
network to host short |
ntohl() |
network to host long |
Все функции возвращают преобразованное значение.
uint32_t some_long = 10; uint16_t some_short = 20; uint32_t network_byte_order; // преобразовываем и отсылаем network_byte_order = htonl(some_long); send(s, &network_byte_order, sizeof(uint32_t), 0); some_short == ntohs(htons(some_short)); // это выражение истинно |
Предыдущая | Оглавление | Следующая |