Как отправлять целые числа через QTcpSocket?

Я новичок в Qt, так что если это совсем глупый вопрос...

Я пытаюсь использовать QTcpSocket.

If I do:

...
QTcpSocket * socket
socket = new QTcpSocket(this);
socket.write(1);
...

Он жалуется на то, что write() не работает с целыми числами (не const char *).

If I do:

...
QTcpSocket * socket
socket = new QTcpSocket(this);
socket.write("1");
...

другая сторона видит его как целое число 49 (ASCII для 1).

По аналогичной, но другой проблеме можно ли отправлять структуры или объединения через QTcpSocket?

==================================================

ИЗМЕНИТЬ:

Сервер уже принимает целые числа и ожидает целое число - я не могу это контролировать.


person Sagar    schedule 16.08.2011    source источник
comment
На самом деле недостаточно сказать, что сервер ожидает целое число. Сервер ожидает серию байтов, представляющих целое число. Как это целое число кодируется (что входит в байты), количество байтов и порядок байтов — это то, что вам нужно знать. и отправить вместе с любыми другими специфическими для протокола байтами, если таковые имеются.   -  person Arnold Spence    schedule 16.08.2011


Ответы (4)


Проблема, с которой вы столкнулись, на самом деле не связана с Qt, такая же проблема может возникнуть с любым другим интерфейсом Socket или Streaming.

Поставщик сервера должен предоставить вам описание протокола. Это описание обычно содержит используемые порты (TCP, UDP, номера), другие параметры TCP и кодировку передаваемых данных. Иногда этот протокол (или его реализацию) называют (протокольным) стеком.

Кодирование содержит не только порядок байтов, но и описание того, как передаются сложные структуры. Последняя информация часто закодирована в чем-то, что называется «ASN.1» — абстрактная синтаксическая нотация.

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

foreach (int i in my set of integers)
{
   ioDevice->write((const char*) &i, sizeof(i));
}

Вы берете адрес своего целого числа в качестве начала буфера данных и передаете столько байтов, сколько имеет ваше целое число. Но обратите внимание, что это не удастся, если вы передадите данные из архитектуры Intel в 16-битную архитектуру или Motorola PPC.

person Jens    schedule 16.08.2011
comment
Я уже знаю адрес TCP, номера портов и т. д. Проблема связана с Qt, потому что, если я использую реализацию сокета, предоставляемую sys/socket.h в unix (например), я могу отправлять структуры, целые числа, что угодно еще, что я как. Я просто хочу знать, могу ли я сделать это здесь, т.е. отправить целые числа. Ничего общего с порядком байтов или стеком протоколов... - person Sagar; 16.08.2011
comment
Я думаю, что с моей или с вашей стороны осталось некоторое недопонимание: какую именно функцию из sys/socket.h вы имеете в виду? - person Jens; 17.08.2011
comment
Если вы используете стандартный сокет, предоставляемый gcc, вы можете писать напрямую в sockfd, используя write(). [См. здесь][linuxhowtos.org/C_C++/socket.htm]. Только что узнал, что могу сделать то же самое с qtcpsocket write() - person Sagar; 17.08.2011
comment
Ага, вот что мне помогло! Спасибо! - person Sagar; 17.08.2011

Я предлагаю использовать QDataStream с сокетами. Это защитит вас от проблемы преобразования little endian/big endian.

Итак, что-то вроде ниже:

qint32 myData = 1;
QDataStream os( &mySocket );
os << myData;
person O.C.    schedule 17.08.2011

Когда вы пишете в строковом представлении, вы также должны интерпретировать строку с другой стороны. Например, есть QString::toInt().

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

В принципе, можно копировать структуры и т. д. в буфер, а также по сети. Однако все снова усложняется, когда вы передаете данные между разными архитектурами или даже только между разными сборками вашего программного обеспечения. Таким образом, вы не должны отправлять необработанные данные, а использовать сериализацию! См. этот вопрос: Сериализация с помощью Qt

Он дает ответы о том, как генерировать потоки из объектов и объекты из потоков. Эти потоки — это то, что вы затем используете для передачи по сети. Тогда вам больше не придется иметь дело с целыми числами!

person ypnos    schedule 16.08.2011
comment
Спасибо! Я попробую отправить данные с помощью потоков данных, хотя я не уверен, что сервер увидит это правильно. Опубликую обратно. - person Sagar; 16.08.2011
comment
Нет, похоже, мне нужно отправить либо само целое число, а затем другие вещи, либо структуру, содержащую целое число и другие вещи... - person Sagar; 16.08.2011
comment
Вы уверены, что QDataStream не работает? См. этот пример: doc.qt.nokia.com/latest/network-fortuneclient. html - person ypnos; 17.08.2011
comment
Это пример, которому я пытался следовать. Может я что то не так сделал, но сервер его не правильно увидел. Я знаю, что сервер плохо запрограммирован (он довольно старый), но, к сожалению, он не в моих руках. - person Sagar; 17.08.2011
comment
Я понимаю. Это не было ясно в первоначальной версии вопроса. Затем сервер ожидает число не в прозрачном для сети порядке байтов, а в машинном порядке байтов. Это отстой. Чтобы быть в безопасности, вы должны заботиться о порядке байтов, явно преобразовывая в порядок байтов этой машины. - person ypnos; 17.08.2011
comment
Да, извините за это. Я должен был указать это. Спасибо за помощь, правда! - person Sagar; 17.08.2011

Различные перегрузки, вы ищете:

qint64 QIODevice::write ( const char * data, qint64 maxSize );

и

qint64 QIODevice::write ( const QByteArray & byteArray );
person Nikolai Fetissov    schedule 16.08.2011
comment
Я знаю две перегрузки. Мне просто интересно, есть ли способ отправлять целые числа. Спасибо хоть! - person Sagar; 16.08.2011