C++ 从QLocalSocket读取超过2048字节
我在从QLocalSocket读取超过2048字节时遇到问题。 这是我的服务器端代码:C++ 从QLocalSocket读取超过2048字节,c++,sockets,qt5,C++,Sockets,Qt5,我在从QLocalSocket读取超过2048字节时遇到问题。 这是我的服务器端代码: clientConnection->flush(); // <-- clientConnection is a QLocalSocket QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_5_0); out << (quint16)
clientConnection->flush(); // <-- clientConnection is a QLocalSocket
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_0);
out << (quint16)message.size() << message; // <--- message is a QString
qint64 c = clientConnection->write(block);
clientConnection->waitForBytesWritten();
if(c == -1)
qDebug() << "ERROR:" << clientConnection->errorString();
clientConnection->flush();
clientConnection->flush();
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_0);
out << (quint16)0;
out << message;
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));
qDebug() << "Bytes client should read" << (quint16)(block.size() - sizeof(quint16));
qint64 c = clientConnection->write(block);
clientConnection->waitForBytesWritten();
QDataStream in(sock);
in.setVersion(QDataStream::Qt_5_0);
while(sock->bytesAvailable() < sizeof(quint16)){
sock->waitForReadyRead();
}
quint16 btr;
in >> btr;
qDebug() << "Need to read" << btr << "and we have" << sock->bytesAvailable() << "in sock";
while(sock->bytesAvailable() < btr){
sock->waitForReadyRead();
}
in >> received_message;
qDebug() << received_message;
客户端代码:
clientConnection->flush(); // <-- clientConnection is a QLocalSocket
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_0);
out << (quint16)message.size() << message; // <--- message is a QString
qint64 c = clientConnection->write(block);
clientConnection->waitForBytesWritten();
if(c == -1)
qDebug() << "ERROR:" << clientConnection->errorString();
clientConnection->flush();
clientConnection->flush();
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_0);
out << (quint16)0;
out << message;
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));
qDebug() << "Bytes client should read" << (quint16)(block.size() - sizeof(quint16));
qint64 c = clientConnection->write(block);
clientConnection->waitForBytesWritten();
QDataStream in(sock);
in.setVersion(QDataStream::Qt_5_0);
while(sock->bytesAvailable() < sizeof(quint16)){
sock->waitForReadyRead();
}
quint16 btr;
in >> btr;
qDebug() << "Need to read" << btr << "and we have" << sock->bytesAvailable() << "in sock";
while(sock->bytesAvailable() < btr){
sock->waitForReadyRead();
}
in >> received_message;
qDebug() << received_message;
QDataStream-in(sock);
in.setVersion(QDataStream::Qt_5_0);
while(sock->bytesavable()waitForReadyRead();
}
16 btr;
在>>btr;
qDebug()已收到_消息;
qDebug()out.setVersion(QDataStream::Qt_5_0);
out>
以反序列化对象。因此,在确保接收到所有数据之前,您不能使用它。这让我们想到:
TCP没有用于分离“记录”中数据的内置机制。您不能只发送一些字节,后跟一个“记录标记”,告诉接收者他已经收到了与记录相关的所有数据。TCP提供的是原始字节流。最后,您可以(半)关闭连接,向另一个对等方发出传输结束的信号
1+2意味着您必须使用其他机制(在接收方)来了解您是否已经拥有所需的所有数据,或者您必须等待更多数据。例如,您可以引入带内标记,如\r\n
(如IRC或-在一定程度上-HTTP do)
《财富》示例中的解决方案是在“实际”数据(带有《财富》消息的序列化QString)前面加上该数据的长度(以字节为单位);然后发送长度(16位整数),后跟数据本身
接收器首先读取长度;然后它读取了那么多字节,然后它知道它可以解码财富。如果没有足够的可用数据(长度-即,您收到的数据少于2个字节-和有效负载本身),客户机将什么也不做,等待更多数据
请注意:
- 这种设计并不是新的:大多数协议都是这样做的。在“标准”TCP/IP堆栈中,TCP、IP、Ethernet等在其“头”中都有一个字段,用于指定有效负载(或整个“记录”)的长度李>
- “length”的传输使用一个以特定字节顺序发送的16位无符号整数:它不是memcpy()d进入缓冲区,而是QDataStream用于存储和读取它。虽然这看起来很琐碎,但实际上已经完成了所使用协议的定义
- 如果QDataStream能够从短读取中恢复(即通过抛出异常并将数据留在设备中),则不需要发送有效负载的长度,因为QDataStream已经发送字符串的长度(作为32位无符号双端整数),后跟UTF-16字符李>
out.setVersion(QDataStream::Qt_5_0);
out>
以反序列化对象。因此,在确保接收到所有数据之前,您不能使用它。这让我们想到:
TCP没有用于分离“记录”中数据的内置机制。您不能只发送一些字节,后跟一个“记录标记”,告诉接收者他已经收到了与记录相关的所有数据。TCP提供的是原始字节流。最后,您可以(半)关闭连接,向另一个对等方发出传输结束的信号
1+2意味着您必须使用其他机制(在接收方)来了解您是否已经拥有所需的所有数据,或者您必须等待更多数据。例如,您可以引入带内标记,如\r\n
(如IRC或-在一定程度上-HTTP do)
《财富》示例中的解决方案是在“实际”数据(带有《财富》消息的序列化QString)前面加上该数据的长度(以字节为单位);然后发送长度(16位整数),后跟数据本身
接收器首先读取长度;然后它读取了那么多字节,然后它知道它可以解码财富。如果没有足够的可用数据(长度-即,您收到的数据少于2个字节-和有效负载本身),客户机将什么也不做,等待更多数据
请注意:
- 这种设计并不是新的:大多数协议都是这样做的。在“标准”TCP/IP堆栈中,TCP、IP、Ethernet等在其“头”中都有一个字段,用于指定有效负载(或整个“记录”)的长度李>
- “length”的传输使用一个以特定字节顺序发送的16位无符号整数:它不是memcpy()d进入缓冲区,而是QDataStream用于存储和读取它。虽然这看起来很琐碎,但实际上已经完成了所使用协议的定义
- 如果QDataStream能够从短读取中恢复(即通过抛出异常并将数据留在设备中),则不需要发送有效负载的长度,因为QDataStream已经发送字符串的长度(作为32位无符号双端整数),后跟UTF-16字符李>
您必须检查可用字节数是否等于或大于您期望接收的字节数。通常情况下,如果没有足够的数据可读取,您可以从readyRead插槽返回,当更多数据到来时,它将再次被调用。@Archie bytesAvailable()返回4KB(我希望是2KB),所以这应该可以。至于第二个电话,那是办不到的。我需要在一次调用中完成所有操作(根据Qt文档,这是可能的,我只需要等待数据,我就是这么做的)。您必须检查bytesAvailable是否等于或大于您希望接收的任何值。通常情况下,如果没有足够的数据可读取,您可以从readyRead插槽返回,当更多数据到来时,它将再次被调用。@Archie bytesAvailable()返回4KB(我希望是2KB),所以这应该可以。至于第二个电话,那是办不到的。我需要在一次通话中完成所有工作(根据Qt文档,这是可能的,我只需要等待数据,我会这样做)。谢谢您的回复。我更新了我的代码