Сокеты Qt и Endianness - PullRequest
       20

Сокеты Qt и Endianness

6 голосов
/ 19 апреля 2010

Я пишу программу, которая использует QUdpSocket для передачи данных по сети. Это моя первая программа для сокетов, и я столкнулся с интересной проблемой, называемой Endianness.

Мой реальный вопрос, нужно ли мне беспокоиться о Endianness, когда я использую QNetwork в качестве библиотеки сокетов? Если мне нужно беспокоиться, что мне нужно сделать, чтобы должным образом избежать проблем с Endianness?

Заранее спасибо.

Ответы [ 5 ]

11 голосов
/ 19 апреля 2010

Как правило, вам нужно беспокоиться о порядке байтов (порядке байтов) при передаче целых чисел, превышающих один байт, с одного компьютера на другой. В C / C ++ это означает, что если вы отправляете что-то вроде 16-разрядного, 32-разрядного или 64-разрядного целого числа, вам необходимо сначала преобразовать целое число в сетевой порядок байтов , (также известный как как Big-Endian). Компьютер на принимающей стороне должен затем преобразовать входящие целые числа в порядок байтов хоста , который является любым порядком байтов, который хост-машина использует изначально. Обычно это делается с помощью библиотечных функций серии htons и ntohs, но с библиотекой Qt вы также можете использовать функции qToBigEndian и qFromBigEndian.

Обратите внимание, что вам не нужно беспокоиться о порядке байтов при отправке текста ASCII или UTF-8, поскольку эти форматы состоят из последовательностей отдельных байтов, а не многобайтовых типов данных.

2 голосов
/ 19 апреля 2010

Если вы передаете двоичные данные между двумя машинами с разным порядком байтов, вам, возможно, придется беспокоиться.

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

Если вы передаете данные в известном формате, таком как изображение, то формат изображения обычно имеет что-то в заголовкечтобы показать, в каком порядке он был записан, и библиотека чтения / записи будет обрабатывать его.Если вы изобретаете свой собственный двоичный формат - тогда вам решать.Возможно, вам также придется учитывать размер, сколько байтов - это int на другом компьютере?

Хорошая новость: большинство машин принадлежат Intel, и для большинства приложений будет работать доставка небольших объемов данных в формате ascii.

1 голос
/ 03 мая 2011

Я знаю, что на этот вопрос давным-давно ответили, но я просто подумала, что добавлю к нему.

Вместо использования функций преобразования в порядковый номер вы можете использовать функциональность QDataStream any QIODevice), которая на намного проще и интуитивнее в моем мнение. Конечно, это может заблокировать использование QDataStream как для отправителя, так и для получателя, но в этом случае оно того стоит.

Пример использования, для чужого образца отправки изображения:

QDataStream & operator<< (QDataStream& stream, const QImage& image);
QDataStream & operator>> (QDataStream& stream, QImage& image);
(Оба из них уже реализованы в Qt.)

QTcpSocket *tcp = ...;
QImage img = ...;
QDataStream(tcp) << img;

1 голос
/ 19 апреля 2010

Вот простой тест на случайный порядок байтов, если вы этого хотите:

// Этот тест принимает int как минимум 2.

static const int testValue = 1;

# define is_bigendian () (( (char ) & testValue) == 0)

bool CD_is_bigendian (void) { return is_bigendian (); }

0 голосов
/ 19 апреля 2010

Процессоры Intel используют порядок байтов. Большая часть всего остального имеет порядковый номер. Сетевой порядок байтов по умолчанию - big endian.

Чтобы проверить, является ли проблема порядком байтов, отправьте значение 0x12345678 и проверьте, соответствует ли оно тому же или 0x78563412. Если значение на принимающем компьютере является более поздним значением, то порядок байтов в двух системах не одинаков.

Проверьте эту статью в Википедии для получения информации о порядке байтов.

...