【问题标题】:How do I read a class object from a QTcpSocket using a QDataStream?如何使用 QDataStream 从 QTcpSocket 读取类对象?
【发布时间】:2017-07-18 01:44:44
【问题描述】:

我有一个由我定义的类,比如MyClass。我想通过QTcpSocket 发送此类的对象。 This answer 建议使用 QDataStreamthis 显示如何重载 <<>> 运算符来实现此目的。

到目前为止,我已经设法为QDataStream 重载了<<>> 运算符。对于发送和接收部分,我遵循Marek Rthis answer 的指示,它回答了一个或多或少与这个问题重复的问题。我发送MyClass 对象的服务器代码似乎可以工作。但是,我无法弄清楚如何从QDataStream 接收和格式化数据。

来自Marek R'sanswer

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;
    }
}

但是,当我使用它时,我得到一个错误:

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

根据发送方式,我尝试如下:

    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;
    }

但是,这会产生以下错误:

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

供参考,以下是发送代码,编译成功(读取代码正常后无法检查):

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);

我对网络概念不是很熟悉,所以我可能遗漏了一些琐碎的东西。

我该怎么做?

另外,块开头发送的quint16(0)有什么意义呢?据称它可以作为块大小的指标,但它是如何做到的呢?无论块大小是多少,它都不是一样的吗?还是我完全误解了它的用法?

谢谢。

【问题讨论】:

  • 为什么不简单地编写 serializeToJson 和 deserializeFromJson 函数呢?会更简单。
  • @MherDidaryan 我认为只能以这种方式发送字符串。您能否举个例子,或指出一个来源?
  • 是的,你发送字节(QByteArray)。 QJsonDocument 具有返回 QByteArray 的 toJson 方法。

标签: c++ qt sockets qtcpsocket qdatastream


【解决方案1】:

如果 MyClass 实现了QJsonObject serializeToJson() and void deserializeFromJson(const QJsonObject&amp;),你可以发送你的类的 json 表示。我认为这样会更简单。

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());

我省略了 json 检查部分。 parsing json

【讨论】:

  • 谢谢。我将如何实现serializeToJson()deserializeFromJson()?此外,如果我的类有指针类型怎么办?这个方法可以处理吗?
  • QJsonObject 有插入功能。 jsonObj.insert("name", this->getName());你的指针类型也可以实现 Serializable 接口。
猜你喜欢
  • 2013-11-09
  • 1970-01-01
  • 1970-01-01
  • 2013-02-21
  • 1970-01-01
  • 2021-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多