Details
Description
The error code set by QTcpSocket::waitForReadyRead() is incorrect if the remote host has closed the connection and a timeout occurred in a previous call.
If the disconnection happens during the first call to QTcpSocket::waitForReadyRead(), the error code is correctly set to QTcpSocket::RemoteHostClosedError. If a timeout occurred during this first call, the error code is QTcpSocket::SocketTimeoutError, which is correct; but after this, in any subsequent call to QTcpSocket::waitForReadyRead(), if the remote host closes the connection, the error code is QTcpSocket::SocketTimeoutError instead of QTcpSocket::RemoteHostClosedError.
Here is a test case. There must be a server listening on port 12345 on localhost (for example, use nc -l 12345). If the server closes the connection (Ctrl-C with nc) within the first call to QTcpSocket::waitForReadyRead(), everything is correct, but if a timeout occurred at least once, the error code will be incorrect.
#include <QTcpSocket> #include <iostream> const QString DEFAULT_HOST = "localhost"; const int DEFAULT_PORT = 12345; const int READ_TIMEOUT = 3000; // ms int main(int argc, char *argv[]) { QTcpSocket socket; socket.connectToHost(DEFAULT_HOST, DEFAULT_PORT); socket.waitForConnected(-1); if (socket.state() != QTcpSocket::ConnectedState) { std::cout << "Error while connecting to host: " << socket.errorString().toUtf8().data() << std::endl; return 1; } while (true) { bool result = socket.waitForReadyRead(READ_TIMEOUT); if (!result) { std::cout << "Error while receiving from host: " << socket.errorString().toUtf8().data() << std::endl; if (socket.state() == QTcpSocket::UnconnectedState) { std::cout << "Disconnected from host." << std::endl; if (socket.error() != QTcpSocket::RemoteHostClosedError) { std::cout << "Problem: socket error code is not RemoteHostClosedError." << std::endl; } return 0; } } } }