Почему QTcpSocket не испускает сигналы?

У меня проблемы с 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,connected и т.д.). На сервере я вижу, что соединение установлено и данные отправлены, но на стороне клиента ничего не происходит. NetworkInstance расширяет QThread.


person graywolf    schedule 13.08.2013    source источник
comment
Если вы создаёте подкласс QThread, вы делаете это неправильно: blog.qt.digia.com/blog/2010/06/17/вы-делаете-это-неправильно   -  person TheDarkKnight    schedule 13.08.2013
comment
Вам вообще не нужен QThread! Вы можете безопасно запускать это в основном потоке, ведь QTcpSocket работает асинхронно.   -  person Marek R    schedule 14.08.2013
comment
Мне нужен QThread, я делаю тяжелую обработку с полученными данными (и да, можно было бы поставить обработку в QThread сам по себе, но так проще). У меня есть один сокет на поток, это соответствует моим потребностям. Однако принятый ответ является решением.   -  person graywolf    schedule 14.08.2013


Ответы (2)


Основываясь на моем предыдущем комментарии о том, что создание подкласса 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();
person TheDarkKnight    schedule 13.08.2013
comment
Менее сложный способ достижения той же цели - создать подкласс QObject И QRunnable, а затем передать работника в QThreadPool. - person RobbieE; 13.08.2013
comment
Не совсем «менее сложный» ИМХО, но я согласен, что это еще один возможный метод. - person TheDarkKnight; 13.08.2013
comment
на самом деле ему вообще не нужен QThread. QTCPSocket работает асинхронно. - person Marek R; 14.08.2013
comment
Верно, но, возможно, его класс будет обрабатывать входящие пакеты и хочет сделать это в другом потоке. - person TheDarkKnight; 14.08.2013

Я уверен, что сигналы излучаются. Я не уверен, что они получены слотами в другом потоке. Должно быть. Обычно.

Qt::Автоподключение

(по умолчанию) Если сигнал испускается из потока, отличного от принимающего объекта, сигнал ставится в очередь, ведя себя как Qt::QueuedConnection. В противном случае слот вызывается напрямую, действуя как Qt::DirectConnection. Тип соединения определяется при излучении сигнала.

Но теперь вы запускаете свой собственный цикл событий с помощью exec() в run().

Редактировать: Ааа... Понятно...

Qt::QueuedConnection

Слот вызывается, когда управление возвращается в цикл обработки событий потока получателя. Слот выполняется в потоке получателя.

Это то, что используется автоматически, поскольку отправитель и получатель находятся в разных потоках. Но с вашим 'exec()' управление никогда не возвращается в поток получателя.

person Greenflow    schedule 13.08.2013
comment
Итак, вы говорите, что мне не следует запускать собственный цикл обработки событий с помощью exec()? Я не уверен, как это будет работать без него, но пробовал и не помогает. - person graywolf; 13.08.2013