简体   繁体   English

QObject:没有这样的插槽QThread :: readyRead()

[英]QObject: no such slot QThread::readyRead()

I am trying to figure out how to correctly use Qt TCP Sockets, as well as multithreading. 我试图弄清楚如何正确使用Qt TCP套接字以及多线程。 I want, as a test project in support of something more complex but similar I will try in the future, to do the following: a simple application that either listens for exactly one incoming connection, or connects to a serversocket; 作为一个支持更复杂但又相似的项目的测试项目,我希望将来做以下工作:一个简单的应用程序,要么只监听一个传入连接,要么连接到服务器插槽; next it prints everything it receives over that socket. 接下来,它将打印通过该套接字接收到的所有内容。

The situation where I connect to a serversocket (I use netcat with the -l option for this) works fine: everything netcat sends to my application is printed correctly. 我连接到serverocket的情况(我将netcat与-l选项一起使用)工作正常:将netcat发送到我的应用程序的所有内容均正确打印。 However, when I use my program to listen for that one incoming connection (generated by netcat), the connecting succeeds but then I get this runtime error: 但是,当我使用程序侦听该传入连接(由netcat生成)时,连接成功,但随后出现此运行时错误:

QObject::connect: No such signal QThread::readyRead() in ..\QTcpTest\listener.cpp:8

Here is the entire code (don't mind the plain CI/OI use sometimes, I'll remove this later): 这是完整的代码(不要介意有时会使用普通的CI / OI,稍后再删除):

[ main.cpp ] [main.cpp]

#include "peer.h"
#include <QCoreApplication>
#include <QThread>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static bool askIfServer();

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Peer *p;
    int rval;
    if (askIfServer())
        p = new Peer;
    else
        p = new Peer(false);
    rval = a.exec();
    delete p;
    return rval;
}

static bool askIfServer()
{
    bool isServer;
    char ibuf[BUFSIZ];

    fputs("Choose \'host\' or \'join\': ", stderr);
    fgets(ibuf, BUFSIZ, stdin);
    ibuf[strlen(ibuf) - 1] = '\0';
    fflush(stdin);

    if (strcmp(ibuf, "host") == 0)
        isServer = true;
    else if (strcmp(ibuf, "join") == 0)
        isServer = false;
    else
    {
        fputs("Failure.\n", stderr);
        exit(-1);
    }

    return isServer;
}

[ peer.h ] [peer.h]

#ifndef PEER_H
#define PEER_H

#include "listener.h"
#include <QObject>
#include <QThread>
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QTcpServer>

class Peer : public QObject
{
    Q_OBJECT
public:
    static const quint16 PORT = 5483;
    explicit Peer(bool isHost = true, QString hostname = "localhost", QObject *parent = 0);
public slots:
    void acceptPeer();
private:
    bool _isHost;
    QTcpServer *_server;
    QTcpSocket *_socket;
    QThread *_lThread;
    Listener *_listener;
};

#endif // PEER_H

[ peer.cpp ] [peer.cpp]

#include "peer.h"

Peer::Peer(bool isHost, QString hostname, QObject *parent) :
    QObject(parent),
    _isHost(isHost)
{
    if (_isHost)
    {
        _server = new QTcpServer;
        connect(_server, SIGNAL(newConnection()), this, SLOT(acceptPeer()));
        _server->listen(QHostAddress::Any, PORT);
    }
    else
    {
        _socket = new QTcpSocket;
        connect(_socket, SIGNAL(hostFound()), this, SLOT(acceptPeer()));
        _socket->connectToHost(hostname, PORT);
    }
}

void Peer::acceptPeer()
{
    disconnect(this, SLOT(acceptPeer()));
    if (_isHost)
    {
        _socket = _server->nextPendingConnection();
        delete _server;
        _server = NULL;
    }

    _lThread = new QThread;
    _listener = new Listener(_socket);
    _listener->moveToThread(_lThread);
    _lThread->start();
}

[ listener.h ] [listener.h]

#ifndef LISTENER_H
#define LISTENER_H

#include <iostream>
#include <QObject>
#include <QByteArray>
#include <QtNetwork/QTcpSocket>
using std::cout;

class Listener : public QObject
{
    Q_OBJECT
public:
    explicit Listener(QTcpSocket *socket, QObject *parent = 0);
public slots:
    void acceptData();
private:
    QTcpSocket *_socket;
};

#endif // LISTENER_H

[ listener.cpp ] [listener.cpp]

#include "listener.h"

Listener::Listener(QTcpSocket *socket, QObject *parent) :
    QObject(parent),
    _socket(socket)
{
    // I guess this is where it goes wrong
    connect(_socket, SIGNAL(readyRead()), this, SLOT(acceptData()), Qt::QueuedConnection);
}

void Listener::acceptData()
{
    QByteArray data = _socket->readAll();
    cout << data.constData();
}

The thing I do not get is that the error message claims that I try to connect some signal from QThread (and I clearly do not: see listener.cpp:8); 我没有得到的是错误消息声称我尝试连接来自QThread的某些信号(并且我显然不这样做:请参见listener.cpp:8)。 even stranger is that this only happens when the socket is created by the QTcpServer instance, not in the other case. 甚至更奇怪的是,这种情况仅在套接字由QTcpServer实例创建时才会发生,而在其他情况下则不会。 What am I missing? 我想念什么?

EDIT: SOLVED 编辑:已解决

See my own answer. 看到我自己的答案。

I do not use an extra thread anymore (see comment). 我不再使用额外的线程(请参阅注释)。 The problem was deleting the QTcpServer instance in Peer::acceptPeer() , once a connection was established. 问题是一旦建立连接,就删除Peer::acceptPeer()的QTcpServer实例。 I thought that I could delete it because I only need that one socket QTcpServer::nextPendingConnection() returns. 我以为可以删除它,因为我只需要返回一个套接字QTcpServer::nextPendingConnection() Apparently this is wrong, the socket is probably destroyed as well, leaving me with a rogue pointer (I think) crashing the program. 显然这是错误的,套接字也可能被破坏,使我留下了流氓指针(我认为)使程序崩溃。 Now I only call _server->pauseAccepting(); 现在我只调用_server->pauseAccepting(); right after I get the socket, and all works fine. 在我获得插座后,一切正常。

Here is the change I've made: 这是我所做的更改:

void Peer::acceptPeer()
{
    disconnect(this, SLOT(acceptPeer()));
    if (_isHost)
    {
        _socket = _server->nextPendingConnection();
        _server->pauseAccepting(); // no deletion
    }

    _listener = new Listener(_socket);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM