QTcpSocket - 在退出QRunnable时指定了无效句柄

时间:2013-06-21 02:46:25

标签: c++ qt sockets tcp

此代码段中出现此错误:

void TCPConnectThread::run()
{
    m_socket = new QTcpSocket();
    m_socket->setSocketDescriptor(m_fd);

    m_socket->waitForReadyRead(10000);

    QString data = m_socket->readAll();

    m_socket->waitForDisconnected();
}

有点深入:

if (::WSAIoctl(socketDescriptor, FIONREAD, &dummy, sizeof(dummy), &nbytes,  
sizeof(nbytes), &sizeWritten, 0,0) == SOCKET_ERROR) <-Exception here
{
    WS_ERROR_DEBUG(WSAGetLastError());
    return -1;
}

更深入:

if (::getsockopt(d->socketDescriptor, SOL_SOCKET, 
SO_ERROR, (char *) &value, &valueSize) == 0) <-Here
退出invalid handle方法时发生

run异常。

以下是我如何获得m_socket:

m_socket = new QTcpSocket();
m_socket->setSocketDescriptor(m_fd);//m_fd is the socket descriptor of another socket
                                    //from another thread

以下是收集m_fd的主题:

void TCPListenerThread::onNewConnection()
{
    QTcpSocket *clientSocket = m_tcpServer->nextPendingConnection();
    int sockfd = clientSocket->socketDescriptor();
    m_connectThread = new TCPConnectThread(sockfd);
    m_threadPool->start(m_connectThread);
}

例外:

Most possible exception at 0x76edf9ea in manager_host.exe:   
0xC0000008: An invalid handle was specified  

我如何以及在何处找到此无效句柄?

1 个答案:

答案 0 :(得分:1)

如果QTcpSocket对象的套接字描述符已被另一个QTcpSocket对象使用,则不能使用该套接字描述符。一旦分配给QTcpSocket

,也没有解除分配的方法

即使你没有明确地使用初始QTcpSocket,如果它创建的线程中有一个事件循环(这可能是这里的情况),Qt将在该线程中监视它。

作为替代方案,您可以:

  • 派生QTcpServer类以重新定义其incomingConnection(int socketDescriptor)方法,以便在将其分配给QTcpSocket之前获取该描述符,而不是使用nextPendingConnection OR
  • 直接将QTcpSocketnextPendingConnection接收而不是套接字描述符作为参数传递给线程构造函数,并将其移动到另一个线程(参见that note) :

    TCPConnectThread(QTcpSocket *socket)
        : m_socket(socket) 
    {
        m_socket−>setParent(0); // necessary to move the object to another thread
        m_socket->moveToThread(this);
        ...
    }
    

    由于必须从初始线程完成移动,因此使用QRunnable可能更容易实现第一个替代方案,因为您可能无法轻松访问将来QThread可运行的将是使用