用QT网络序列化和用Boost反序列化

serialization with QT network and deserialization with Boost

本文关键字:Boost 反序列化 序列化 QT 网络      更新时间:2023-10-16

在第一时间我要感谢HostileFork帮助我解释我的问题。谢谢!

我正在尝试建立一个客户端和服务器谁通过二进制协议发送他们的数据。

我的问题是我想从QT客户端发送一个类到Boost服务器。我的头(一个整数,它是我的类的大小)在套接字上写入。当我想在服务器端读取报头时,我无法得到好的整数(而不是我有一个像-13050660这样的大数字)。我想问题出在服务器上的反序列化,但我不确定。

这是我的Qt客户端代码用于将数字10写入套接字的技术:

QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
out << (quint32) 0;
out.device()->seek(0);
out << (quint32) (10);
cout << "Writing " << sizeof(quint32) << " bytes to socket." << endl;

然后我尝试在服务器进程上读取它,它使用boost的async_read():

this->Iheader.resize(size, ''); // Iheader is a vector of char
async_read(
    this->socket,
    buffer(this->Iheader),
    bind(
        &Client::endRead,
        cli,
        placeholders::error,
        placeholders::bytes_transferred)
);
下面是对字符串结果进行操作的函数:
#ifdef WIN32
    #define MYINT INT32
    #include <Windows.h>
#else
    #define MYINT int
#endif
void Client::endRead(const error_code& error, size_t nbytes)
{
    if (!error && nbytes == sizeof(MYINT)) {
        cout << "Read " << sizeof(MYINT) << " bytes from a socket." << endl;
        istringstream stream(this->connection->getIheader(nbytes));
        stream >> this->Isize;
        cout << "Integer value read was " << this->Isize << endl;
    } else {
        cout << "Could not read " << sizeof(MYINT) << " bytes." << endl;
    }
}

我确实得到了32位有符号整数(4字节),但它不是10,而是类似于-1163005939。有人知道为什么这不起作用吗?

服务器和客户端都在Windows7 pro上启动,64位。

不用谢…感谢您按照我的建议编辑问题,并做了必要的努力来更清楚地指出问题。现在我可以告诉你怎么了。:)

<<>>QDataStream上的行为与在c++标准io流上的行为不同。在像std::stringstream这样的类的世界中,这些操作符被称为"插入器"/"提取器",用于处理格式化为文本的信息。如果您想要将一定数量的字节读入内存地址,您需要的是:

http://www.cplusplus.com/reference/iostream/istream/read/

(注意,如果你想从非字符串流的东西中读取二进制数据,你需要使用ios::binary来防止它干扰行结束转换)

QDataStream不遵循这种惯例…它是二进制数据的好帮手。这没什么错……因为抽象地说,<<>>操作符在语言中是可以重载的,可以在自己的类层次结构中做任何你想做的事情。Qt可以自由地为自己的流定义自己的语义,他们也这样做了。

一定要听从@vitakot给出的建议,即(如果可能的话)对输入和输出使用相同的方法。另外,请注意我的警告,如果你不小心,就会出现字节排序问题。

(好消息是,如果您使用的是QDataStream,它会为您解决这个问题。)

请注意,在您编写的代码中,您的stringstream正在复制缓冲区以便从中读取。我没有boost::asio的经验,也没有async_read的最佳实践,但我相信你可能会找到更好的方法。

HostileFork是对的,从我们拥有的信息来看,不可能在你的代码中隔离一个bug。

但是,我建议您在Qt客户端中也使用boost序列化。没有理由不把Boost和Qt库结合起来。否则,当您通过网络发送更复杂的类时,您将不得不处理许多麻烦…