Сетевой порядок байтов на локальном хосте

0

Я разрабатываю сетевое приложение с использованием Winsock API. Всякий раз, когда я проверяю приложение на отправку нескольких байтов, например, в массив:

char[0] = '1';
char[1] = '2';
char[2] = '3';
char[3] = '4';
char[4] = '\0';

Я использую send и recv socket для приема байтов в другом приложении, запущенном на localhost, тогда порядок байтов вообще не изменяется. Это просто потому, что я тестирую его на сервере localhost? Будет ли порядок байтов сети изменяться следующим образом:

char[0] = '\0';
char[1] = '4';
char[2] = '3';
char[3] = '2';
char[4] = '1';

если я получу его через Интернет?

  • 0
    Насколько я понимаю (и это было источником путаницы для меня), я считаю, что порядок байтов является лишь фактором, когда вы сериализуете многобайтовый объект. Это байты внутри объекта, которые переупорядочиваются. Здесь вы отправляете char которые являются однобайтовыми, поэтому их нельзя переставить. Дело не в том, что весь твой поток переупорядочен. Я не уверен в этом, так что подтверждение было бы неплохо.
  • 0
    возможный дубликат Endianness и Socket Programming в C
Теги:
winapi
winsock
endianness

2 ответа

2
Лучший ответ

8-разрядные массивы символов и строки не попадают в проблемы с порядком байтов сети. Поскольку каждый отдельный символ в массиве уже в порядке с самим собой и упорядочен со следующим байтом символа в массиве... Это короткие, ints и longs, которые оказываются затронутыми.

Кроме того, это не вызовы отправки и recv, которые выполняют любую байтовую подкачку. Обмен байтов связан с тем, как процессор выделяет целые числа в памяти:

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

// code that demonstrates how integer values are laid out in memory
int msg = 0x01020304;
char* buffer = (char*)&msg;
for (int x = 0; x < 4; x++)
    printf("%d %d %d %d\n", buffer[0], buffer[1], buffer[2], buffer[3]);

Результат, который распечатывается:

4 3 2 1

Это показывает, что процессоры x86 упорядочивают байты памяти целых чисел в противоположном порядке, который вы могли бы ожидать. Наименее значащий байт или целое число сначала упорядочивается в памяти. Это Маленький Эндиан.

На чипе Sparc, таком как старая рабочая станция Sun, этот же код печатает:

1 2 3 4

Это Большой Эндиан.

Это только при выводе данных на диск или в сеть, что имеет значение Endianness последовательности памяти. Как только другой компьютер считывает последовательность байтов, выписанную другим компьютером, тогда ЦП, считывающее целое число, будет интерпретировать его на основе собственной сущности.

Обычно при определении целых чисел для передачи файлов или потоковой передачи в сеть обычно имеет значение Endianness. Без преобразования разработчиком приложения необработанный буфер, переданный send(), передается точно так же, как процессор выдает байты в памяти. См. Htonl и friends для получения дополнительной информации о преобразовании целых чисел и коротких сообщений в и из Big Endian (также как порядок байтов сети).

  • 0
    Но если я собираюсь отправить целое число, скажите int i = 256; Мне нужно преобразовать его в массив символов и передать буфер в сокет. Итак, откуда же в этом дело?
  • 1
    Преобразуйте i в сетевой порядок байтов перед отправкой. Пример: int j = htonl(i); send(sock, (char*)&j, sizeof(j), 0); Аналогично, сделайте вызов ntohl () для полученного целого числа при получении его обратно.
Показать ещё 3 комментария
1

Endianness только вступает в игру, когда вы смотрите на поток байтов и решаете интерпретировать данные.

Например, если у вас есть поток байтов:

'1' '2' '3' '4' '0'

И вы решили интерпретировать данные как поток символов, тогда, предполагая один байт на символ, у вас есть массив, содержащий строку "1234".

Однако, если вы решите интерпретировать данные как int то вступает в действие утверждение, поскольку вы используете более одного байта, которые используются для кодирования типа данных (int). Значения вышеуказанного потока имеют шестнадцатеричные значения:

0x31 0x32 0x33 0x34 0x00

(0x31 - это шестнадцатеричное значение "1" и т.д.)

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

  • 0
    Но если я собираюсь отправить целое число, скажите int i = 256; Мне нужно преобразовать его в массив символов и передать буфер в сокет. Так откуда же в этом дело Endianness?
  • 0
    @cpx - если вы хотите отправить тип int вы можете преобразовать его в сетевой порядок байтов, используя htonl ( msdn.microsoft.com/en-us/library/windows/desktop/… ). Затем, когда вы читаете его обратно, используйте ntohl ( msdn.microsoft.com/en-us/library/windows/desktop/… )
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню