简体   繁体   English

如何在QTcpSocket中读取完整数据?

[英]How to read complete data in QTcpSocket?

Now the server (implemented with java) will send some stream data to me, my code is like below: 现在服务器(用java实现)会向我发送一些流数据,我的代码如下:

connect(socket, SIGNAL(readyRead()), this, SLOT(read_from_server()));

in the read_from_server() : read_from_server()

{
    while (socket->bytesAvailable())
    {
        QString temp = socket->readAll();
    }
}

but I find that even the server sent me a string with only several characters, the data is truncated, and my function is called twice, thus temp is the never complete data that I want. 但我发现即使服务器发给我一个只有几个字符的字符串,数据被截断,我的函数被调用两次,因此temp是我想要的永不完整的数据。
If server send me a longer string, my function may be called three or more times, making me diffficult to know at which time the data is transfered completely. 如果服务器发给我一个更长的字符串,我的函数可能会被调用三次或更多次,这使得我很难知道数据完全被传输的时间。
So anyone can tell me how to completely receive the data easily, without so many steps of bothering? 所以任何人都可以告诉我如何轻松完全接收数据,没有这么多困扰的步骤? I'm sorry if this is duplicated with some questions else, I couldn't get their answers work for me. 如果这与其他一些问题重复,我很抱歉,我无法让他们的答案适合我。 Many thanks! 非常感谢!

What you're seeing is normal for client-server communication. 您所看到的是客户端 - 服务器通信的正常现象。 Data is sent in packets and the readyRead signal is informing your program that there is data available, but has no concept of what or how much data there is, so you have to handle this. 数据以数据包形式发送,readyRead信号通知您的程序有可用的数据,但没有关于数据的数据或数据的概念,因此您必须处理此问题。

To read the data correctly, you will need a buffer, as mentioned by @ratchetfreak, to append the bytes as they're read from the stream. 要正确读取数据,您需要一个缓冲区,如@ratchetfreak所述,在从流中读取字节时附加字节。 It is important that you know the format of the data being sent, in order to know when you have a complete message. 了解所发送数据的格式非常重要,以便知道何时有完整的消息。 I have previously used at least two methods to do this: - 我之前使用过至少两种方法来做到这一点: -

1) Ensure that sent messages begin with the size, in bytes, of the message being sent. 1)确保发送的消息以正在发送的消息的大小(以字节为单位)开头。 On receiving data, you start by reading the size and keep appending to your buffer until it totals the size to expect. 在接收数据时,首先要读取大小并继续附加到缓冲区,直到它达到预期的大小。

2) Send all data in a known format, such as JSON or XML , which can be checked for the end of the message. 2)以已知格式发送所有数据,例如JSONXML ,可以检查消息的结尾。 For example, in the case of JSON, all packets will begin with an opening brace '{' and end with a closing brace '}', so you could count braces and match up the data, or use QJsonDocument::fromRawData to verify that the data is complete. 例如,在JSON的情况下,所有数据包将以一个左括号'{'开头,以一个右括号'}'结束,因此您可以计算大括号并匹配数据,或使用QJsonDocument :: fromRawData来验证数据完整。

Having used both of these methods, I recommend using the first; 使用这两种方法后,我建议使用第一种方法; include the size of a message that is being sent. 包括正在发送的消息的大小。

If all of the data has not yet arrived then your while loop will exit prematurely. 如果所有数据尚未到达,则while循环将提前退出。 You need to use a message format that will let the receiving code determine when the complete message has been received. 您需要使用一种消息格式,让接收代码确定何时收到完整的消息。 For example, the message could begin with a length element, or if you are dealing with text the message could end with some character used as a terminator. 例如,消息可以以length元素开头,或者如果您正在处理文本,则消息可能以某些字符作为终止符结束。

you can use a buffer field to hold the unfinished data temporarily and handle packets as they complete: 您可以使用缓冲区字段临时保存未完成的数据并在完成时处理数据包:

{
    while (socket->bytesAvailable())
    {
        buffer.append(socket->readAll());
        int packetSize = getPacketSize(buffer);
        while(packetSize>0)
        {
            handlePacket(buffer.left(packetSize);
            buffer.remove(0,packetSize);
            packetSize = getPacketSize(buffer);
        }
    }
}

Problem is that during tcp data transfer data are send in undefined chunks. 问题是在tcp期间数据传输数据是以未定义的块发送的。 If you are trying to read defined block size you have to know in advance expected chunk size ore have a way to determinate when your block ends (something like zero terminated c-string). 如果您正在尝试读取已定义的块大小,则必须事先知道预期的块大小可以确定块何时结束(类似于零终止的c-string)。

Check if this answer doesn't help you (there is a trick to wait for expected data block). 检查这个答案是否对您没有帮助(有一个等待预期数据块的技巧)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM