0

I have a Qt based TCP client and server making use of QTcpServer and QTcpSocket classes for communication. The server is compiled using Qt 5.3.1 and the client is compiled using Qt 4.8.1. This is done so because the client is a part of a framework that uses Qt 4.8.1 running on Ubuntu 12.04.

Since the classes I make use is available in both Qt versions I assume this wont create a problem.

However my client has some weird issues that it does not receive data from the server! I checked the server side and the data is sent from the server and I can also see the data packet on the wire using wireshark. However on my client code, the data does not arrive!

I investigated this a bit and it led me to a strange conclusion that this happens only if I use the read method of QTcpSocket! If I use the native POSIX read system call, I am able to read the data correctly! Please see my code below:

qDebug() << "QTcpSocket::bytesAvailable() gives" << m_pSocket->bytesAvailable();

char nData;

qint32 szReceived;

if(sizeof(char) != (szReceived = m_pSocket->read((char*)&nData,sizeof(char))))
{
    qDebug() << "Error reading data from QTcpSocket::read()" << m_pSocket->errorString();
}
else
{
    qDebug() << "QTcpSocket::read() returned" << szReceived;
}

int nDesc = m_pSocket->socketDescriptor();

if(sizeof(char) != (szReceived = read(nDesc, &nData,sizeof(char))))
{
    perror("Error reading data from POSIX read()");
}
else
{
    qDebug() << "POSIX read() returned" << szReceived;
}

This produces the following output:

QTcpSocket::bytesAvailable() gives 0 
Error reading data from QTcpSocket::read() "Network operation timed out" 
POSIX read() returned 1

How is it that the POSIX system calls reads the buffered data as expected and the Qt class cannot read it? Plus I have not set any socket options and so I don't know why it reports an error that network operation timed out!

asumang
  • 673
  • 1
  • 6
  • 11

3 Answers3

1

"read" is a blocking call in POSIX, it waits till the data is arrived. while QTcpSocket is non-blocking operation it immediately returns the buffered data. Call waitForReadyRead before doing a read

 socket->waitForReadyRead();
 if(sizeof(char) != (szReceived = m_pSocket->read((char*)&nData,sizeof(char))))
dvasanth
  • 1,337
  • 1
  • 9
  • 10
0

I think that it is misuse of QTcpSocket concept. QTcpSocket implements asynchronous architecture while POSIX read/write calls are blocking until the success or error of I/O on socket. It is much better to process read in slot for readyRead signal. Consider this:

class MyClient
{
  Q_OBJECT

...

private slots:

  readFromSocket();

};

In your intialization:

QObject::connect(
        m_pSocket, SIGNAL(readyRead()),
        this, SLOT(readFromSocket()));

And real job done here:

void
MyClient::readFromSocket()
{
  QByteArray buffer = m_pSocket->readAll();
  // All your data in buffer. 
}
Tanuki
  • 449
  • 2
  • 8
-1

I'm aware of the non-blocking nature of QTcpSocket and blocking nature of POSIX read call. Unfortunately I cannot use the signal readFromSocket because my communication architecture expects a header to be sent before each communication (TCP way) to see the payload that is streamed for that particular message. Hence I have to wait till I receive at least the header.

I do believe that this has something to do with the mode (blocking or non-blocking). I did some more tests and none of them were conclusive. In one of my tests, I tried to call a waitForReadyRead with a timeout of 1ms, 2ms, 3ms. This still wasn't sufficent for the read to succeed! I doubt if the read would need such time to read from the kernel buffers to user space as I can clearly see from wireshark that the message was received within 400ms.

When I give -1 as the timeout value of waitForReadyRead, the read succeeds! To put it in another way, the read succeeds only when the socket waits indefinitely like in the case of POSIX read call.

Another strange thing I observed was, this issue was originally observed when I was running a server compiled using Qt 5.3.1 and client compiled using Qt 4.8.1. When I compile my client to use Qt 5.3.1, I do not see this problem!!! I even tried compiling using Qt 4.7.1 and it worked without any issues!!!

Are there any known issues with socket implementation of Qt 4.8.1? I couldn't find much info regarding this unfortunately.

asumang
  • 673
  • 1
  • 6
  • 11