структура отправки через QTcpSocket

#qt

#qt

Вопрос:

Можем ли мы отправить структуру, содержащую указатели на другие структуры, через сокет QTcpSocket в сокет QTcpServer программы, запущенной в другом физическом расположении, чем эта программа. Мой код будет выглядеть следующим образом….

 <i>
QTcpSocket tcpSocket = new QTcpSocket(this);
Struct a{ int a1; int a2;} __attribute__((packed));

Struct b { int b1; int b2}__attribute__((packed));
Struct c{ a *c1; a*c2; }QByteArray block;

QDataStream out(amp;block, QIODevice::WriteOnly);
out << quint16(0)<<c;
out << quint16(block.size() - sizeof(quint16));
tcpSocket->write(block);
</i>
  

но при этом возникает ошибка, подобная:
/TcpClient-build-desktop/../TcpClient/tcpclient.cpp:137: ошибка: нет соответствия для ‘operator<<’ in ‘out.QDataStream::operator<<(0) << c’

Ответ №1:

Вы можете, если получатель знает, что он не может иметь только указатели, разыменованные процессом отправки. Это означало бы обратную связь с источником и ожидание результата. Этот процесс называется «брокинг объектов» и был реализован, например, в CORBA, COM , jre и других.

Указатель должен интерпретироваться только в известной части виртуальной памяти.

Комментарии:

1. Спасибо. вы имеете в виду, что после отправки пакета TCP отправляющая машина также отправит фактические данные, на которые указывают указатели …?

2. @anjali: возможно, по запросу. Суть в том, что получатель должен рассматривать «указатели» как дескрипторы объектов, которые он не может разрешить сам.

Ответ №2:

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

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

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

Статья в Википедии о порядковом номере.

Комментарии:

1. @anjali Я никогда не видел attribute((packed)) синтаксиса. Это какое-то расширение C ?

2. _attribute_((упакованный)) , сообщает gcc, чтобы исключить все дополнения между элементами.

3. @anjali Хорошо. Это не поможет вам в этом вопросе. Я думаю, вам следует рассмотреть то, что предлагает Дариуш Шарсиг, использовать сериализацию. И, затем, преобразование любых целых чисел.

Ответ №3:

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

С наилучшими пожеланиями
D

Комментарии:

1. Спасибо. Если я правильно вас понимаю, во время отправки фактически поток фактических данных должен быть отправлен тому, на кого указывают указатели?? В QTcpSocket мы добавляем любой объект, такой как блок QByteArray; QDataStream out(amp;block, QIODevice::WriteOnly); out << quint16(0) <<ObjectStructureToSend; out.device()-> seek(0); TCPSocket-> write(блок); итак, как преобразовать фактические данные перед отправкой?

2. Да, именно. Вы перезаписали оператор << в своем ObjectStructureToSend и отправляете туда не сам указатель (что бесполезно, поскольку он содержит адрес в памяти отправляющих машин), а сериализацию структуры, на которую указывает указатель. С другой стороны, при десериализации вы берете эти «данные указателя», создаете объект в куче и устанавливаете указатель на этот адрес.

Ответ №4:

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