gpt4 book ai didi

c++ - 使用 QDataStream 从 QTcpSocket 读取

转载 作者:可可西里 更新时间:2023-11-01 16:59:17 28 4
gpt4 key购买 nike

我需要通过QTcpSocket 发送二进制数据。我正在考虑使用 QDataStream,但我遇到了一个问题 - 如果在我尝试读取时没有数据到达,它会自动失败。

例如,如果我有这段代码:

QString str;
stream >> str;

如果套接字中当前没有数据,它将静默失败。有没有办法告诉它改为阻止?

最佳答案

问题有点严重。 Socket 可以分块接收数据,因此即使您等待 waitForReadyRead,它也可能会失败,因为没有足够的数据来立即读取某个对象。
要解决此问题,您必须先发送一定大小的数据,然后再发送实际数据。发送代码:

QByteArray block;
QDataStream sendStream(&block, QIODevice::ReadWrite);
sendStream << quint16(0) << str;

sendStream.device()->seek(0);
sendStream << (quint16)(block.size() - sizeof(quint16));

tcpSocket->write(block);

在接收器上,您必须等待可用数据的大小满足要求。接收器代码看起来或多或少像这样:

void SomeClass::slotReadClient() { // slot connected to readyRead signal of QTcpSocket
QTcpSocket *tcpSocket = (QTcpSocket*)sender();
QDataStream clientReadStream(tcpSocket);

while(true) {
if (!next_block_size) {
if (tcpSocket->bytesAvailable() < sizeof(quint16)) { // are size data available
break;
}
clientReadStream >> next_block_size;
}

if (tcpSocket->bytesAvailable() < next_block_size) {
break;
}
QString str;
clientReadStream >> str;

next_block_size = 0;
}
}


小更新,基于 documentation可以在不添加额外大小信息的情况下读取 QString,因为传递给 QDataStream 的 QString 包含大小信息。大小可以这样验证:

void SomeClass::slotReadClient() { // slot connected to readyRead signal of QTcpSocket
QTcpSocket *tcpSocket = (QTcpSocket*)sender();
while(true) {
if (tcpSocket->bytesAvailable() < 4) {
break;
}
char buffer[4]
quint32 peekedSize;
tcpSocket->peek(buffer, 4);
peekedSize = qFromBigEndian<quint32>(buffer); // default endian in QDataStream
if (peekedSize==0xffffffffu) // null string
peekedSize = 0;
peekedSize += 4;
if (tcpSocket->bytesAvailable() < peekedSize) {
break;
}
// here all required for QString data are available
QString str;
QDataStream(tcpSocket) >> str;
emit stringHasBeenRead(str);
}
}

关于c++ - 使用 QDataStream 从 QTcpSocket 读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19681564/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com