简体   繁体   English

如何使用QDataStream从QTcpSocket读取类对象?

[英]How do I read a class object from a QTcpSocket using a QDataStream?

I have a class defined by me, say MyClass . 我有一个由我定义的类,例如MyClass I would like to send an object of this class through a QTcpSocket . 我想通过QTcpSocket发送此类的对象。 This answer suggests using a QDataStream , and this shows how the << and >> operators can be overloaded to achieve this. 该答案建议使用QDataStream表明如何可以重载<<>>运算符以实现此目的。

I have so far managed to overload the << and >> operators for QDataStream . 到目前为止,我已经设法为QDataStream重载<<>>运算符。 For the sending and receiving part, I am following directions from this answer by Marek R , which answers a question that is more or less a duplicate of this one. 对于发送和接收部分,我遵循的是Marek R的 回答 ,该回答回答的问题或多或少是该问题的重复。 My server code, which sends the MyClass object seems to work. 发送MyClass对象的服务器代码似乎正常工作。 However, I am not able to figure out how to receive and format the data from the QDataStream . 但是,我无法弄清楚如何从QDataStream接收和格式化数据。

From Marek R's answer , 根据Marek R的 回答

void SomeClass::slotReadClient() { // slot connected to readyRead signal of QTcpSocket
    QTcpSocket *tcpSocket = (QTcpSocket*)sender();
    QDataStream clientReadStream(tcpSocket);

    while(true) {
        if (!next_block_size) {
            if (tcpSocket->bytesAvailable() < sizeof(quint16)) { // are size data available
                break;
            }
            clientReadStream >> next_block_size;
        }

        if (tcpSocket->bytesAvailable() < next_block_size) {
            break;
        }
        QString str;
        clientReadStream >> str;

        next_block_size = 0;
    }
}

However, when I use this, I get an error: 但是,当我使用它时,出现错误:

error: no matching function for call to ‘QDataStream::QDataStream(QTcpSocket*&, QIODevice::OpenModeFlag)’

Based on the method of sending, I tried as follows: 根据发送方法,我尝试如下:

    MyClass obj;
    QByteArray block;
    QDataStream rs(&block,QIODevice::ReadWrite);
    rs.setVersion(QDataStream::Qt_5_7);
    int nextblocksize = 0;
    while(true)
    {
        if(!nextblocksize)
        {
            if(socket->bytesAvailable() < sizeof(quint16))
            {
                break;
            }
            socket->read(block,socket->bytesAvailable());
            rs>>nextblocksize;
        }
        if(socket->bytesAvailable() < nextblocksize)
        {
           break;
        }
        socket->read(block,socket->bytesAvailable());
        rs>>obj;
        nextblocksize=0;
    }

However, this gives the following error: 但是,这产生以下错误:

error: conversion from ‘QByteArray’ to ‘char*’ is ambiguous
             socket->read(block,socket->bytesAvailable());
                                                        ^

For reference, the following is the code for sending, which compiles succesfully (can't check till the code for reading is working): 作为参考,以下是用于发送的代码,该代码可以成功编译(在读取代码工作之前,无法检查):

QTcpSocket *socket = server->nextPendingConnection();
QByteArray block;
MyClass obj(1,2.0, "Hi\n");
QDataStream ds(&block,QIODevice::ReadWrite);
ds.setVersion(QDataStream::Qt_5_7);
ds<<quint16(0)<<obj;
socket->write(block);

I am not very familiar with networking concepts, so I might be missing something trivial. 我对网络概念不是很熟悉,所以我可能缺少一些琐碎的东西。

How do I do this? 我该怎么做呢?

In addition, what is the significance of the quint16(0) sent at the beginning of the block? 另外,在块的开头发送的quint16(0)的意义是什么? It is claimed that it serves as an indicator of the size of the block, but how does it do this? 据称它可以作为块大小的指标,但是它是如何做到的呢? Isn't it the same irrespective of what the block size is? 不管块大小是多少,都是一样的吗? Or have I completely misunderstood its usage? 还是我完全误解了它的用法?

Thank you. 谢谢。

If MyClass implements QJsonObject serializeToJson() and void deserializeFromJson(const QJsonObject&) you could send json representation of your class. 如果MyClass实现了QJsonObject serializeToJson() and void deserializeFromJson(const QJsonObject&) ,则可以发送类的json表示形式。 I think it would be simpler in this way. 我认为这样会更简单。

class Serializable
{
public:
Serializable(){}
virtual ~Serializable(){}

virtual QJsonObject serialize_to_json() = 0;
};

class Deserializable
{
public:
Deserializable(){}
virtual ~Deserializable(){}
virtual void deserialize_from_json(const QJsonObject&) = 0;
};

// MyClass implements Serializable and Deserializable
MyClass obj;

// To wrire
// construct QJsonDocument from serializeToJson
// write bytes representing the json 
// QJsonDocument::toJson() returns QByteArray
socket->write(QJsonDocument(obj.serializeToJson()).toJson());


// To read
// Construct QJsonDocument from received bytes
// QJsonDocument::fromJson(bytes).toObject returns QJsonObject
MyClass obj;
obj.deserializeFromJson(QJsonDocument::fromJson(socket->readAll()).toObject());

I omit json checking part. 我省略了json检查部分。 parsing json 解析json

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM