为啥 QTcpSocket 不发出信号?

Posted

技术标签:

【中文标题】为啥 QTcpSocket 不发出信号?【英文标题】:Why QTcpSocket does not emit signals?为什么 QTcpSocket 不发出信号? 【发布时间】:2013-08-13 14:24:40 【问题描述】:

我在使用 QTcpSocket 时遇到问题,它没有发出任何信号:/


void NetworkInstance::run()

    m_pSocket = new QTcpSocket();
    connect(m_pSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError()));
    connect(m_pSocket, SIGNAL(hostFound()), this, SLOT(socketHostLookupDone()));
    connect(m_pSocket, SIGNAL(connected()), this, SLOT(socketConnected()));
    connect(m_pSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));

    connect(m_pSocket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()));

    QSettings s;
    s.beginGroup("network");
    emit log(QString("Connection to: ").append(s.value("host").toString()).append(":").append(s.value("port").toString()));
    m_pSocket->connectToHost(s.value("host").toString(), s.value("port").toInt());
    s.endGroup();

    exec();

这是我的代码,我没有看到任何错误,但没有发出已连接的信号(hostFound、已连接等)。在服务器上,我可以看到已建立连接并发送了数据,但客户端没有任何反应。 NetworkInstance 正在扩展 QThread。

【问题讨论】:

如果你是 QThread 的子类,“你做错了”:blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong 你根本不需要QThread!在所有 QTcpSocket 异步工作之后,您可以安全地在主线程中运行它。 我需要 QThread,我对接收到的数据进行了一些繁重的处理(是的,可以将处理本身放入 QThread,但这样更简单)。我每个线程有一个套接字,它适合我的需要。然而,公认的答案就是解决方案。 【参考方案1】:

根据我之前的评论,子类化 QThread 是错误的,您需要做的是创建从 QObject 继承的类,然后将其移动到新的 QThread。

所以你会有一个看起来像这样的类:-

class NetworkInstance : public QObject

    Q_OBJECT

public:
    NetworkInstance();

public slots:
    void Run();

    void socketConnected();
    void socketError();
    // etc for other slots...

private:
    class QTCPSocket* m_pSocket;

创建您的网络实例对象和线程:-

QThread* pThread = new QThread;
NetworkInstance* pNetworkInstance = new NetworkInstance;

创建 QTCPSocket 实例并连接 NetworkInstance 类中的信号/插槽,然后创建 QThread 并将您的类移动到线程:-

pNetworkInstance->moveToThread(pThread);

最后,启动线程运行:-

pThread->start();

【讨论】:

实现相同目的的一种不太复杂的方法是将 QObject 和 QRunnable 子类化,然后将工作线程传递给 QThreadPool 不完全是,'不那么复杂'恕我直言,但我同意这是另一种可能的方法。 事实上他根本不需要QThread。 QTCPSocket 异步工作。 是的,但也许他的班级会处理传入的数据包,并希望在不同的线程上执行此操作。【参考方案2】:

我确定信号已发出。我不太确定它们是否被另一个线程中的插槽接收。应该。一般。

Qt::AutoConnection

(默认)如果信号是从不同的线程发出的,而不是 接收对象,信号被排队,表现为 Qt::QueuedConnection。否则,直接调用槽, 表现得像 Qt::DirectConnection。确定连接类型 当信号发出时。

但是现在你在 run() 中使用 exec() 开始你自己的事件循环。

编辑:啊……我明白了……

Qt::QueuedConnection

当控制返回到 接收者线程的事件循环。该插槽在 接收者的线程。

这是自动使用的,因为发送者和接收者在不同的线程中。但是使用你的 'exec()' 控件永远不会返回到接收者的线程。

【讨论】:

so.. 你说我不应该用 exec() 开始自己的事件循环吗?我不确定没有它它会如何工作,但尝试了它并没有帮助。

以上是关于为啥 QTcpSocket 不发出信号?的主要内容,如果未能解决你的问题,请参考以下文章

QTcpSocket readyRead() 信号多次发出

QTcpSocket 不会发出任何错误或连接信号

Qt - 当一个类中有多个 QTcpSocket 时,我如何知道哪个 QTcpSocket 发出了 readyRead 信号?

QTcpSocket Disconnected() 未发出信号

Qt的QTcpSocket ReadyRead信号的实现

QTcpSocket 问题