Qt QIODevice :: write / QTcpSocket ::写入和写入的字节

时间:2011-09-22 09:31:02

标签: c++ qt sockets

我们对QIODevice::write的行为以及QTcpSocket具体的行为感到非常困惑。已经有similar question,但答案并不令人满意。主要的混淆源于那里分别提到bytesWritten信号的waitForBytesWritten方法。这两个似乎表明从QIODevice使用的缓冲区写入到实际底层设备的字节(必须有这样的缓冲区,否则该方法没有多大意义)。那么问题是,如果QIODevice::write返回的数字与此数字相对应,或者在这种情况下,它表示内部缓冲区中存储的字节数< / em>,而不是写入底层设备的字节。如果返回的数字表示写入内部缓冲区的字节,我们需要采用如下的模式来确保写入所有数据:

void writeAll(QIODevice& device, const QByteArray& data) {
   int written = 0;
   do {
     written = device.write(data.constData() + written, data.size() - written);
   } while(written < data.size());
}

但是,如果QIODevice::write的返回值与bytesWritten信号的含义相对应,则会插入重复数据。文档对此非常困惑,因为在两种方法中都使用了 device 这个词,即使它似乎是逻辑和一般的理解,一个实际上表示写入缓冲区而不是设备。

总而言之,问题是:#e QIODevice::write返回的数字是写入底层设备的字节数,因此保存到QIODevice::write 而不用检查返回的字节数,因为所有内容都存储在内部缓冲区中。或者它是否表明它可以在内部存储多少字节,并且必须采用类似上述writeAll的模式来安全地将所有数据写入设备?

(更新:查看源代码,QTcpSocket::write实现实际上永远不会返回比想要写的字节少的字节,因此不需要上面的writeAll。但是,这是特定于套接字的而这个Qt版本,文档仍然令人困惑......)

2 个答案:

答案 0 :(得分:5)

QTcpSocket是一个缓冲的QAbstractSocket。在QAbstractSocket内分配内部缓冲区,并在该缓冲区中复制数据。 write的返回值是传递给write()的数据的大小。

waitForBytesWritten等待,直到QAbstractSocket的内部缓冲区中的数据写入本机套接字。

答案 1 :(得分:1)

上一个问题回答了您的问题,QIODevice::write(const char * data, qint64 maxSize)文档也是如此:

  

将数据的最多 maxSize字节数据写入设备。返回实际写入的字节数,如果发生错误,则返回-1。

这可以(并且将在现实生活中)返回少于您请求的内容,并且您可以再次使用其余内容再次致电write

至于waitForBytesWritten

  

对于缓冲设备,此函数会一直等到缓存的写入数据的有效负载写入设备...

它仅适用于缓冲设备。并非所有设备都是缓冲的。如果它们是,并且您写入的内容少于缓冲区可容纳的内容,write可以在设备完成所有数据的发送之前成功返回。

设备不一定是缓冲的。