3

此代码段中发生此错误:

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 handlerun退出方法时发生异常。

这是我获得 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  

我如何以及在哪里可以找到这个无效的句柄?

4

1 回答 1

1

QTcpSocket如果对象的套接字描述符已被另一个对象使用,则不能使用该对象的套接字描述符QTcpSocket。一旦分配给一个,也没有取消分配它的方法QTcpSocket

即使您没有显式使用 initial QTcpSocket,如果在创建它的线程中有一个事件循环(这里可能就是这种情况),Qt 也会在该线程中监视它。

作为替代方案,您可以:

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

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

    由于必须从初始线程完成移动,第一个替代方案可能更容易使用 a QRunnable,因为您可能无法轻松访问QThreadrunnable 将使用的未来。

于 2013-06-21T13:08:22.820 回答