Tcp packets using QTcpSocket

2019-01-05 05:40发布

I know that TCP guarantees that all packets will arrive. But can a packet be separated into 2 or more? I am using Qt with class QTcpSocket, and I want to know is ReadyRead() signal is emitted only when full packet arrives. Or in other words, is there any sense to send packet size in first bytes and then wait in loop until all bytes had arrived? Or I can just call socket->readAll() and I must get one full packet?

标签: qt tcp
1条回答
放荡不羁爱自由
2楼-- · 2019-01-05 05:50

If a large amount of data is sent, the packet can arrive in separate parts. Alternatively, multiple messages can be received in one readyRead slot.

It's good practice to control this by setting the first byte(s) to the number of bytes that will be sent. Then, in readyRead, you read the first bytes and append the data to a buffer until the expected amount of data has been received.

In receiving data, this also means that if multiple messages are received in one call to readyRead(), you can know where the first message ends and the next one begins.

Here's an example of a client that receives data in a readyRead function()

void MyClass::readyRead()
{
    // m_pConnection is a QTcpSocket

    while(m_pConnection->bytesAvailable())
    {
        QByteArray buffer;

        int dataSize;
        m_pConnection->read((char*)&dataSize, sizeof(int));
        buffer = m_pConnection->read(dataSize);

        while(buffer.size() < dataSize) // only part of the message has been received
        {
            m_pConnection->waitForReadyRead(); // alternatively, store the buffer and wait for the next readyRead()
            buffer.append(m_pConnection->read(dataSize - buffer.size())); // append the remaining bytes of the message
        }

        QString msg(buffer); // data in this case is JSON, so we can use a QString
        emit Log(QString("\tMessage Received: %1").arg(msg));

        // Do something with the message
        ProcessMessage(msg);
    }
}
查看更多
登录 后发表回答