如何将数据作为 QByteArray/QDataStream 从服务器发送到客户端

3
在Qt的fortuneserver样例中,通过方法sendFortune()发送了一个QString。因此需要从QStringList fortunes中选择一个QString。
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << (quint16)0;
out << fortunes.at(qrand() % fortunes.size());
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));

QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
clientConnection->write(block);

除了单个字符串外,是否还可以发送其他类型的数据,例如文件、图像或多个字符串?

我的第二个问题是:将数据发送为QByteArry的优势是什么,为什么我需要通过设置QDataStream来定义(quint16)


简单来说,客户端/服务器通信使用像TCP这样的协议。该协议封装您的消息以到达目的地。消息是字节。字节可以是图像、字符串、文件或任何东西,因为一切都是字节。关于quint16问题,您需要理解需要定义发送/接收消息的规则,否则您将永远不知道消息何时开始和结束。 - Martin
有没有任何示例?因为这是事实 - 我想要理解它 - 但是没有一些练习,很难理解。... 字符串应该使用哪个大小,图像或文本文件应该使用哪个大小...我不知道...一些帮助会很棒。 - 3ef9g
你不必担心这些大小。请记住,TCP通信是流通信。因此,您在任何时间都会收到0101101010101...。您必须定义自己的规则(或使用一些应用协议,如HTTP)来知道消息的开头和结尾。假设您想发送一个字符串“hello”。您首先写入0x00 0x00以知道这是消息的开头。然后您写下hello。然后您写下您字符串的大小0x05。因此,您在套接字上发送00 00 68 65 6c 6c 6f 00 05。 - Martin
另一方面,您将收到00 00 68 65 6c 6c 6f 00 05。首先,您需要取最后2个字节00 05,计算出您期望的消息长度为5个字节。因此,您从第3个字节开始读取,因为前两个字节是00 00,然后您得到了68 65 6c 6c 6f。这是一个长度为5的有效消息。所以你有了你的“hello”字符串。为什么要这么复杂?因为使用TCP时,您需要通过数据包进行通信,并且您不知道需要多少个数据包来传输您的数据,也无法确定是否成功接收所有数据包。 - Martin
2个回答

3
您不需要将数据发送为QDataStream,QDataStream是一个模拟流的类,一种传输数据的方式,就像电线一样。 QByteArray代表您的数据的存储。 因此,您可以将数据作为QByteArray发送。 您可以尝试QTcpSocket的成员函数"int write(QByteArray)",就像您提供的示例中一样。只需取图像、文件、任何其他数据并将其转换为QByteArray。这就是您需要QDataStream的地方。将流绑定到字节数组上,如下所示。 QByteArray dat; QDataStream out(&dat, QIODevice::WriteOnly); 使用out来填充dat。 out << myImage << myImage2; 当您完成填充QByteArray时,发送它: mySocket.write(dat); 不要忘记检查返回值。 阅读文档,您将成功。

0
为了知道您是否已经读取了套接字另一侧发送的所有数据,我使用了QDataStream中的commitTransaction()函数:
Client::Client()
{
    ....
    connect(tcpSocket, &QIODevice::readyRead, this, &Client::readData);
    ....
}

void Client::readData()
{
    in.startTransaction();

    QString data;
    in >> data;

    if (!in.commitTransaction())
    {
        qDebug() << TAG << "incomplete: " << data;
        // readyRead will be called again when there is more data
        return;
    }

    // data is complete, do something with it
    ....

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接