Сокеты Qt и Endianness

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

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

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

5 ответов


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

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


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

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

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

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


вот простой тест для big endianness, если вы этого хотите:

// этот тест предполагает размер int не менее 2.

static const int testValue = 1;

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

bool CD_is_bigendian (void) { возврат is_bigendian(); }


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

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

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

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

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


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

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

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