QTcpSocket读取错误

时间:2014-08-13 16:34:55

标签: c++ qt sockets qtcpsocket

我有一个基于Qt的TCP客户端和服务器,它使用QTcpServer和QTcpSocket类进行通信。服务器使用Qt 5.3.1编译,客户端使用Qt 4.8.1编译。这样做是因为客户端是使用在Ubuntu 12.04上运行的Qt 4.8.1的框架的一部分。

由于我使用的类在两个Qt版本中都可用,我认为这不会产生问题。

但是我的客户端有一些奇怪的问题,它不会从服务器接收数据!我检查了服务器端,数据是从服务器发送的,我也可以使用wireshark查看线路上的数据包。但是在我的客户端代码上,数据没有到达!

我对此进行了一些研究,这让我得出一个奇怪的结论,即只有使用QTcpSocket的read方法才会发生这种情况!如果我使用本机POSIX读取系统调用,我能够正确读取数据!请参阅下面的代码:

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;
}

这会产生以下输出:

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

POSIX系统调用如何按预期读取缓冲数据并且Qt类无法读取它?另外,我没有设置任何套接字选项,因此我不知道为什么它会报告网络操作超时的错误!

3 个答案:

答案 0 :(得分:0)

“read”是POSIX中的阻塞调用,它等待数据到达。当QTcpSocket是非阻塞操作时,它立即返回缓冲的数据。在执行读取之前调用waitForReadyRead

 socket->waitForReadyRead();
 if(sizeof(char) != (szReceived = m_pSocket->read((char*)&nData,sizeof(char))))

答案 1 :(得分:0)

我认为这是对QTcpSocket概念的误用。 QTcpSocket实现异步体系结构,而POSIX读/写调用阻塞,直到套接字上的I / O成功或错误。为readyRead信号处理插槽读取要好得多。考虑一下:

class MyClient
{
  Q_OBJECT

...

private slots:

  readFromSocket();

};

在您的初始化中:

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

在这里完成了真正的工作:

void
MyClient::readFromSocket()
{
  QByteArray buffer = m_pSocket->readAll();
  // All your data in buffer. 
}

答案 2 :(得分:-1)

我知道QTcpSocket的非阻塞性质和阻止POSIX读取调用的性质。不幸的是,我无法使用信号readFromSocket,因为我的通信架构需要在每次通信(TCP方式)之前发送标头,以查看为该特定消息流式传输的有效负载。因此,我必须等到我收到至少标题。

我确实认为这与模式有关(阻塞或非阻塞)。我做了一些测试,但没有一个是决定性的。在我的一个测试中,我尝试调用waitForReadyRead,超时为1ms,2ms,3ms。这仍然不足以使读取成功!我怀疑读取是否需要这样的时间从内核缓冲区读取到用户空间,因为我可以从wireshark清楚地看到消息是在400ms内收到的。

当我将-1作为waitForReadyRead的超时值时,读取成功!换句话说,只有当套接字无限期地等待POSIX读取调用时,读取才会成功。

我观察到的另一个奇怪的事情是,这个问题最初是在我运行使用Qt 5.3.1编译的服务器和使用Qt 4.8.1编译的客户端时观察到的。当我编译我的客户端使用Qt 5.3.1时,我没有看到这个问题!我甚至尝试使用Qt 4.7.1进行编译,它没有任何问题!

Qt 4.8.1的套接字实现是否存在任何已知问题?不幸的是,我找不到很多关于此的信息。