我们对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版本,文档仍然令人困惑......)
答案 0 :(得分:5)
QTcpSocket
是一个缓冲的QAbstractSocket
。在QAbstractSocket
内分配内部缓冲区,并在该缓冲区中复制数据。 write的返回值是传递给write()
的数据的大小。
waitForBytesWritten
等待,直到QAbstractSocket
的内部缓冲区中的数据写入本机套接字。
答案 1 :(得分:1)
上一个问题回答了您的问题,QIODevice::write(const char * data, qint64 maxSize)
文档也是如此:
将数据的最多 maxSize字节数据写入设备。返回实际写入的字节数,如果发生错误,则返回-1。
这可以(并且将在现实生活中)返回少于您请求的内容,并且您可以再次使用其余内容再次致电write
。
对于缓冲设备,此函数会一直等到缓存的写入数据的有效负载写入设备...
它仅适用于缓冲设备。并非所有设备都是缓冲的。如果它们是,并且您写入的内容少于缓冲区可容纳的内容,write
可以在设备完成所有数据的发送之前成功返回。
设备不一定是缓冲的。