QTcpSocket接收转移

Nik*_*ika 1 c++ qt qtcpsocket

我收到转账时遇到问题.

当我发送它时,QTcpSocket-> readAll()没有读取足够的字节.当我发送像15k字节时,它只读取它的一部分,然后什么都不做.我做错了什么?

QByteArray array;

array = socket->readAll(); //just reads some part, not fully.
Run Code Online (Sandbox Code Playgroud)

为什么?

对不起我的英语不好.

问候.

lee*_*mes 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);
Run Code Online (Sandbox Code Playgroud)

处理时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
    }
}
Run Code Online (Sandbox Code Playgroud)

当您想要读取通过一个TCP连接发送的所有内容时(直到它被对等方关闭),您可以以阻塞方式等待此事件,或者处理连接到正确信号的插槽中的数据:QTcpSocket::disconnected.

阻塞:

socket->waitForDisconnected();
QByteArray array = socket->readAll();
Run Code Online (Sandbox Code Playgroud)

非阻塞(使用插槽处理信号):

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);
}
Run Code Online (Sandbox Code Playgroud)

替代非阻塞解决方案(基本相同):

// You don't have to connect to QTcpSocket::readyRead() signal in this case

void MyClass::socketDisconnected()
{
    processMessage(socket->readAll());
}
Run Code Online (Sandbox Code Playgroud)