2016-03-24 7 views
0

Я придерживался учебника о потоковой qt-networking (который находится здесь: http://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html), я внес некоторые незначительные изменения и интегрировал его в свою основную программу. Однако incomingConnection() никогда не будет выполнен, с другой стороны, клиент может подключиться к. Поскольку я хотел бы работать с incomingConnection(), он устарел, чтобы работать с SIGNAL(newConnection()), но даже это не работает.QtNetwork: Почему я не обнаруживаю подключаемые соединения? (incomingConnection() никогда не запускается)

Кто-то знает, что происходит не так?

Вот мой .h

#include <QtNetwork> 
#include <QTcpServer> 
#include <QTcpSocket> 
#include <QThread> 

class WirelessNetThread: public Thread 
{ 
    Q_OBJECT 

public: 
    WirelessNetThread(int socketDescriptor, QObject * parent); 

    void run() Q_DECL_OVERRIDE; 

signals: 
    void error(QTcpSocket::SocketError socketError); 

private: 
    int socketDescriptor; 
    QString text; 
}; 

class WirelessNet : public QTcpServer 
{ 
    Q_OBJECT 

public: 
    WirelessNet(QObject *parent = 0); 

protected: 
    void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE; 

}; 

И .cpp

WirelessNetThread::WirelessNetThread(int socketDescriptor, QObject *parent):QThread(parent), socketDescriptor(socketDescriptor) 
{ 
} 

void WirelessNetThread::run() 
{ 
    QTcpSocket tcpSocket; 
    if (!tcpSocket.setSocketDescriptor(socketDescriptor)) 
    { 
     emit error(tcpSocket.error()); 
     return; 
    } 

    tcpSocket.disconnectFromHost(); 
    tcpSocket.waitForDisconnected(); 
} 

WirelessNet::WirelessNet(QObject *parent): QTcpServer(0) 
{ 
    listen(QHostAddress::Any, 5220); 
    printf("is listening %d\n", this->isListening()); 
} 

void WirelessNet::incomingConnection(qintptr socketDescriptor) 
{ 
    qDebug() << "incomming \n"; 
    printf("incomming \n"); 
    WirelessNetThread *thread = new WirelessNetThread(socketDescriptor, this); 
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); 
    thread->start(); 
} 

здесь отрывок из моей основной программы, где она инициирована (кстати это не имеет значения, если я уйду из moveToThread():

WirelessNet *wifi = new WirelessNet(this->parent()); 
wifi->moveToThread(this->thread()); 

Даже это не имеет никакого влияния, если добавить эти строки после инициализационной из WiFi:

wifi = new WirelessNet(this->parent()); 
QEventLoop testLoop; 
testLoop.exec(); 

Других слов «не Incomming» не печатается вне, и поэтому я не в состоянии работать. У кого-нибудь есть идея, это в значительной степени 1: 1 код из учебника, вот что меня смущает.

+1

Этот код из учебника? ... у вас есть ссылка на него? - его либо очень старый, либо очень плохо написанный (Qt-wise). Я изо всех сил пытаюсь понять, как когда-либо вызывается «incomingConnection()», есть ли сигнал, связанный с ним? Но прежде чем вы заходите слишком далеко в этом ... есть много возиться с наследованием потоков и запуском циклов событий ... все это не требуется и делает его очень грязным для наблюдения и поддержки. Я буквально просто разместил ответ на темы здесь: http://stackoverflow.com/questions/36201769/threads-event-loop-in-the-qt-application/36208479#36208479 - посмотрите на использование QThread –

+0

.. для вы добавили 4 строки кода в стандартный класс Qt, чтобы поместить его в поток. Тогда весь код в вашем классе WirelessNet может сосредоточиться на «вещах беспроводной сети» и бессмысленной бессмысленности:). Я мог бы опубликовать ответ с тем, как я буду реализовывать то, что вы делаете ... но мне все еще не хватает, как вызывается 'incomingConnection()' ... –

+0

@code_fodder ссылка на учебник упоминается в самой первой строке , У меня была/была такая же борьба за 'incomingConnection()'. AFAIU эта функция является переопределенной функцией (т. Е. Виртуальной функцией), которая имеет аналогичные механизмы, такие как переопределенная функция 'run()', если вы наследуете класс из 'QThread'.К сожалению, у меня не было времени, чтобы поближе посмотреть – user3085931

ответ

1

В вашей основной код:

WirelessNet *wifi = new WirelessNet(0); // 0 = assign no parent 
QThread *wifiThread = new QThread; 
wifi->moveToThread(wifiThread); 
QObject::connect(wifiThread, SIGNAL(started()), wifi, SLOT(startWifi())); 
// start() will start its own event loop, it will emit started(), therefore startWifi() slot will be called. 
wifiThread->start(); 

Тогда ваш WirelessNet класс заголовок:

class WirelessNet : public QTcpServer 
{ 
    Q_OBJECT 

public: 
    WirelessNet(QObject *parent = 0); 

protected: 
    void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE; 

public slots: 
    void startWifi(); 
}; 

Тогда ваш WirelessNet тело класса:

WirelessNet::WirelessNet(QObject *parent) : 
    QTcpServer(parent) 
{ 
    // Do nothing much here because we want to initialise new stuff in our thread. 
    // When this function runs we have not moved this to the new thread - or even started it. 
} 

void WirelessNet::incomingConnection(qintptr socketDescriptor) 
{ 
    qDebug() << "incomming \n"; 
    printf("incomming \n"); 
    WirelessNetThread *thread = new WirelessNetThread(socketDescriptor, this); 
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); 
    thread->start(); 
} 

// Called when the thread has started 
void WirelessNet::startWifi() 
{ 
    // Anything done here is now safely within out new thread. 
    listen(QHostAddress::Any, 5220); 
    printf("is listening %d\n", this->isListening()); 
} 

примечание это пример кода, Я написал его непосредственно в переполнение стека, он не был mpiled, поэтому, вероятно, есть некоторые ошибки :) Есть некоторые ключевые моменты, которые я прокомментировал, где вы, возможно, ошиблись в своей первоначальной попытке.

+0

Я, честно говоря, не получаю такого поведения. Теперь тело 'WirelessNet()' пусто и 'startWifi()' как указано в вашем коде. Раньше было наоборот: 'startWifi()' был практически пуст, а конструктор 'WirelessNet()' слушал(). Теперь он работает, и я доволен этим, но не могли бы вы объяснить мне разницу? – user3085931

+1

Дело в том, что (я пытался объяснить в комментариях, но плохо), когда вы создаете свой объект wifi, называется c'tor (т. Е. WirelessNet :: WirelessNet()). Все, что вы создадите здесь, будет создано в потоке, который создал wifi - т. Е. Основной поток. Поэтому я удалил ваш звонок. Затем после того, как вы сделаете wifi.moveToThread (...); а затем запустите поток (thread-> start()) ваш объект wifi теперь живет в новом потоке (и поток также становится его родителем). Кроме того, поскольку мы подключили сигнал QThread :: started() к слоту WirelessNet :: startWifi(), когда поток запускает его, он испускает сигнал и ... –

+1

... запускается startWifi(). Обратите внимание, что все, что запускается в этой функции/слоте, теперь будет запущено в новом потоке. Поэтому я переместил вашу функцию listen() сюда. Там, где другие незначительные проблемы с вашей исходной настройкой (например, назначением родителя) имеют другой взгляд на мои комментарии, я только прокомментировал, где происходит что-то интересное. Я не могу сказать 100%, почему перемещение прослушивания внутри потока работает, потому что я не знаю, что слушает ... но если он создаст какие-то объекты, они будут не в том месте (нить)! –