1

So I have a strange issue that when I read data (QDataStream) on a QTcpSocket: some of the data seems to be missing. The bytesAvailable() function will return the proper amount of bytes to be read, but QDataStream doesn't seem to hold all the bytes.

First of all, this is how the data looks:

enter image description here

bufferX always contains 768 floats and bufferY always contains 5376 floats. Therefore, I would expect the total data to be sent to be (excluding block size) : int + 768 floats + 5376 floats = 4 + 3072 + 21504 = 24580 bytes.

Now, here is the sender code:

void ClientSocket::serverTaskResult()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_DefaultCompiledVersion);

    out << quint16(0);

    out << mServerTask->getNPoints();

    for (size_t i = 0; i < BUFFERX_SIZE; i++)
        out << mServerTask->getBufferX(i);

    for (size_t i = 0; i < BUFFERY_SIZE; i++)
        out << mServerTask->getBufferY(i);

    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));

    write(block);

    out << quint16(0xFFFF);
}

And here is the receiver code:

void TestClient::recoverResult()
{
    QDataStream in(&mTcpSocket);
    in.setVersion(QDataStream::Qt_DefaultCompiledVersion);

    float wBufferX[BUFFERX_SIZE];
    float wBufferY[BUFFERY_SIZE];
    int wNPoints;

    forever{
        if (mNextBlockSize == 0) 
        {
            qint64 nBytesAvailable = mTcpSocket.bytesAvailable();
            if (nBytesAvailable < sizeof(quint16))
                break;
            in >> mNextBlockSize;
        }

        if (mNextBlockSize == 0xFFFF) 
        {
            closeConnection();
            break;
        }

        if (mTcpSocket.bytesAvailable() < mNextBlockSize)
            break;

        for (size_t i = 0; i < BUFFERX_SIZE; i++)
            in >> wBufferX[i];

        for (size_t i = 0; i < BUFFERY_SIZE; i++)
            in >> wBufferY[i];

        in >> wNPoints;

        mNextBlockSize = 0;
    }
}

Now, the first odd thing I'm noticing is that nBytesAvailable always has a value of 49158, which is about double of what I'm expecting. How is it that I'm receiving twice as many bytes as expected?

Secondly, since I have all these bytes available, I would expect the QDataStream to be able to properly fill in the buffers. However, after anywhere between 315 and 350 floats, the QDataStream seems to contain unavailable data. That is, wBufferX will have defined (and correct) values in its first 315-350 indexes and unknown values afterwards. I don't understand how that is since bytesAvailable() clearly indicates that almost 50 000 bytes are on the socket. What am I missing?

Your help is greatly appreciated! Thanks!

RBL92
  • 21
  • 3
  • 1
    Firstly, TCP is stream based so you can't assume one write from the server will result in one read on the client -- you shouldn't *expect* `mTcpSocket.bytesAvailable()` to return any particular value. Secondly you call `write(block)` and then immediately update `block` indirectly using `out << quint16(0xFFFF);`. Finally, you call `out.device()->seek(0);`: I'm not sure performing a seek on a device currently managed by a `QDataStream` is valid/supported. – G.M. Jan 10 '20 at 18:10
  • 1
    You come out from your read function before you have read everything. When you have bytesAvailable less then the size you stop the data reading. I think you should read until you receive all data or timeout. Have you looked at the Qt QTcpSocket examples? – Cristi Jan 10 '20 at 19:06
  • I should have probably mentioned that this `recoverResult()` function from the client is linked to `onReadyRead()`. Therefore, the function will get called over and over until `mTcpSocket.bytesAvailable() < mNextBlockSize` is false, in which case all the data should be available on the socket. The `seek(0)` also works as expected and is something I found in quite a few different examples. Hope that clarifies things a bit! – RBL92 Jan 10 '20 at 19:50

0 Answers0