使用QT网络进行序列化并使用Boost进行反序列化

时间:2011-11-21 19:28:59

标签: c++ qt boost-asio boost-serialization qtnetwork

我想第一次感谢 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, '\0'); // 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个字节),但它不是十个,而是类似于-1163005939。任何人都有并且想出为什么这不起作用?

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

2 个答案:

答案 0 :(得分:1)

欢迎您...并感谢following my suggestions编辑问题,并做出必要的努力以更清楚地查明问题。所以现在我可以告诉你什么是错的。 :)

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

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

(请注意,如果您希望从不是字符串流的内容中读取二进制数据,则需要using ios::binary以避免混乱使用行结束转换)

QDataStream不遵循该惯例......它是二进制数据的好帮手。没有错......因为抽象地说,<<>>运算符在语言中可用于重载以在您自己的类层次结构中执行任何您想要的操作。 Qt可以自由地为自己的流定义自己的语义,并且确实如此。

请注意@vitakot给出的建议(如果可能的话)使用相同的输入和输出方法。如果你不小心的话,还要留意关于byte-ordering issues开始出现的警告。

(好消息是,如果您使用的是QDataStream,则可以taking care of it for you解决此问题。)

请注意,在您编写的代码中,您的字符串流正在制作缓冲区的副本以便从中读取。我对boost::asioasync_read的最佳做法没有经验,但我确信有更好的方法可以挖掘并找到。

答案 1 :(得分:0)

HostileFork是对的,根据我们所掌握的信息,您无法隔离代码中的错误。

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