我遇到接收转移的问题。
QTcpSocket-> readAll()在发送时没有读取足够的字节数。当我发送像15k字节时,它只读取它的一部分,然后什么都不做。我做错了什么?
QByteArray array;
array = socket->readAll(); //just reads some part, not fully.
为什么?
抱歉我的英文。
问候。
答案 0 :(得分:6)
当你致电readAll()
时,插座很可能还没有收到所有数据。这是因为TCP通信发生在小数据包(每个数据包含大约1KB,具体取决于很多事情)。这些数据包组成一个流,通信线路的另一端将字节写入。你必须在接收方组装它们。如何组装它们必须在协议中定义。
要解决此问题,您必须在组装之前等待所有预期的数据。有时不知道有多少数据是预期的,除非你阅读它(取决于协议)。
假设您要实现一个协议,该协议会说“除了换行符之外的所有内容都是我们称之为消息”。现在您想要收到这样的消息。这是通过连续读取并附加到目标缓冲区(如QByteArray
)直到出现换行符来完成的。但是,还有另一件事:当您期望第二个消息时,它可以紧接在TCP流中的第一个消息之后,因此您不仅可以读取第一条消息的结尾,还可以读取第二个开始。请记住这一点。
当不处理信号插槽连接时,您可以为这样的换行符分隔的消息编写同步接收器,如下所示:
QByteArray array;
while(!array.contains('\n')) {
socket->waitForReadyRead();
array += socket->readAll();
}
int bytes = array.indexOf('\n') + 1; // Find the end of message
QByteArray message = array.left(bytes); // Cut the message
array = array.mid(bytes); // Keep the data read too early
processMessage(message);
处理QTcpSocket::readyRead()
时,您可以执行类似的操作。
void MyClass::socketReadyRead() // connected to QTcpSocket::readyRead() signal
{
array += socket->readAll();
if(array.contains('\n')) {
int bytes = array.indexOf('\n') + 1; // Find the end of message
QByteArray message = array.left(bytes); // Cut the message
array = array.mid(bytes); // Keep the data read too early
processMessage(message);
socketReadyRead(); // re-call myself to process more
}
}
当您想要读取通过一个TCP连接发送的所有内容时(直到它被对等方关闭),您可以以阻塞方式等待此事件,或者处理连接到正确信号的插槽中的数据:{{ 1}}。
封闭:
QTcpSocket::disconnected
非阻塞(使用插槽处理信号):
socket->waitForDisconnected();
QByteArray array = socket->readAll();
替代非阻塞解决方案(基本相同):
void MyClass::socketReadyRead() // connected to QTcpSocket::readyRead() signal
{
array += socket->readAll();
// Do NOT process yet!
}
void MyClass::socketDisconnected() // connected to QTcpSocket::disconnected() signal
{
processMessage(array);
}