Qt - 如何在新线程中处理 QTcpSocket

6
尝试从全局线程池中创建新线程来处理已连接的客户端套接字:
m_threadPool = QThreadPool::globalInstance();

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

这是:
class TCPConnectThread : public QRunnable {
    TCPConnectThread::TCPConnectThread(QTcpSocket *_socket)
    {
        m_socket = _socket;
        this->setAutoDelete(false);
    }


    void TCPConnectThread::run()
    {
        if (! m_socket->waitForConnected(-1) )
            qDebug("Failed to connect to client");
        else
            qDebug("Connected to %s:%d %s:%d", m_socket->localAddress(), m_socket->localPort(), m_socket->peerAddress(), m_socket->peerPort());

        if (! m_socket->waitForReadyRead(-1))
            qDebug("Failed to receive message from client") ;
        else
            qDebug("Read from client: %s",   QString(m_socket->readAll()).toStdString().c_str());

        if (! m_socket->waitForDisconnected(-1))
            qDebug("Failed to receive disconnect message from client");
        else
            qDebug("Disconnected from client");
    }
}

我一直在遇到这些无尽的错误。似乎跨线程的 QTcpSocket 处理不可行(请查看 Michael 的答案)。
一些错误:
QSocketNotifier: socket notifiers cannot be disabled from another thread  

ASSERT failure in QCoreApplication::sendEvent: "Cannot send events t objects owned by a different thread.  

我应该在不同的线程中处理 QTcpSocket 吗?
如果我想在不同的线程中处理 QTcpSocket,我应该怎么做?
或者有没有办法从文件描述符创建 QTcpSocket

1个回答

8
我认为这个页面包含了你需要的答案:

如果你想要将一个新的QTcpSocket对象作为另一个线程中的传入连接进行处理,你需要将socketDescriptor传递到另一个线程,并在那里创建QTcpSocket对象并使用其setSocketDescriptor()方法。

为了实现这一点,你需要继承自QTcpServer并重写虚拟方法incomingConnection

在该方法内部,创建子线程,该子线程将为子套接字创建一个新的QTcpSocket

例如:

class MyTcpServer : public QTcpServer
{
protected:
    virtual void incomingConnection(int socketDescriptor)
    {
         TCPConnectThread* clientThread = new TCPConnectThread(socketDescriptor);
         // add some more code to keep track of running clientThread instances...
         m_threadPool->start(clientThread);
    }
};

class TCPConnectThread : public QRunnable
{
private:    
    int m_socketDescriptor;
    QScopedPointer<QTcpSocket> m_socket;

public:
    TCPConnectionThread(int socketDescriptor)
        : m_socketDescriptor(socketDescriptor)
    {
        setAutoDelete(false);
    }

protected:    
    void TCPConnectThread::run()
    {
        m_socket.reset(new QTcpSocket());
        m_socket->setSocketDescriptor(m_socketDescriptor);

        // use m_socket
    }
};

或者尝试在套接字上使用 moveToThread()

moveToThread() 似乎只能与 QThread 一起使用,但我正在使用 QRunnable。 - CDT
1
然后尝试将“socketDescriptor”传递给“TCPConnectThread”构造函数,并在线程的“run”方法中创建一个新的“QTcpSocket”。 - huysentruitw
这是我的程序输出: 从客户端读取:数据 与客户端断开连接 已连接到客户端 从客户端读取:数据 与客户端断开连接 已连接到客户端 从客户端读取:数据 与客户端断开连接 已连接到客户端 从客户端读取:[失败] 与客户端断开连接 - CDT
不,它不会返回任何内容。我用 [failed] 替换了它... 如果我想用一个 waitForReadyRead 读取所有数据,我该怎么做呢?这是可能的吗? - CDT
首先阻塞线程30秒?这将是非常不好的设计。所以:使用循环并添加一些代码来决定何时断开客户端的连接。 - huysentruitw
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接