此代码段中出现此错误:
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
我如何以及在何处找到此无效句柄?
答案 0 :(得分:1)
如果QTcpSocket
对象的套接字描述符已被另一个QTcpSocket
对象使用,则不能使用该套接字描述符。一旦分配给QTcpSocket
即使你没有明确地使用初始QTcpSocket
,如果它创建的线程中有一个事件循环(这可能是这里的情况),Qt将在该线程中监视它。
作为替代方案,您可以:
QTcpServer
类以重新定义其incomingConnection(int socketDescriptor)
方法,以便在将其分配给QTcpSocket
之前获取该描述符,而不是使用nextPendingConnection
OR 直接将QTcpSocket
从nextPendingConnection
接收而不是套接字描述符作为参数传递给线程构造函数,并将其移动到另一个线程(参见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
可运行的将是使用