2016-03-24 17 views
0

Ich hielt mich an das Tutorial über Thread-QT-Netzwerk (das ist hier: http://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html), habe ich ein paar kleinere Änderungen und integriert es in meinem Hauptprogramm. Jedoch wird incomingConnection() niemals ausgeführt, auf der anderen Seite ist der Client in der Lage zu verbinden. Da ich gerne mit incomingConnection() arbeiten würde, wurde es veraltet, mit der SIGNAL(newConnection()) zu arbeiten, aber selbst das funktioniert nicht.QtNetwork: Warum erkenne ich eingehende Verbindungen nicht? (incomingConnection() wird nie ausgelöst)

Jemand weiß, was schief läuft?

meine hier .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; 

}; 

Und die .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(); 
} 

hier der Auszug aus meinem Hauptprogramm, wo es (übrigens initiiert wird es spielt keine Rolle, ob ich auslassen moveToThread():

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

Auch hat dies keinen Einfluss, wenn ich diese Zeilen nach dem initialisiert von wifi hinzufügen:

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

Mit anderen Worten: „incomming“ wird nie gedruckt, und ich bin so nicht in der Lage zu arbeiten. Hat jemand eine Idee, das ist so ziemlich 1: 1 der Code aus dem Tutorial, der mich verwirrt.

+1

Dieser Code stammt aus einem Tutorial? ... Haben Sie einen Link dazu? - es ist entweder sehr alt oder sehr schlecht geschrieben (Qt-weise). Ich habe Probleme zu sehen, wie "incomingConnection()" jemals aufgerufen wird - ist ein Signal damit verbunden? Aber bevor du zu weit gehst ... es gibt viel Unordnung mit erben von Threads und dem Starten von Event-Loops .... all das ist nicht erforderlich und macht es sehr unordentlich zu folgen und zu warten. Ich habe gerade eine Antwort bezüglich Threads hier geschrieben: http://stackoverflow.com/questions/36201769/threads-event-loop-in-the-qt-application/36208479#36208479 - schauen Sie sich die Verwendung von QThread –

+0

.. für Sie seine 4 Zeilen Code extra zu Ihrem Standard-Qt-Klasse, um es in einen Thread zu setzen. Dann kann sich der gesamte Code in Ihrer WirelessNet-Klasse auf "Funknetzwerke" und keinen Thread-Unsinn konzentrieren:). Ich könnte eine Antwort schreiben, mit der ich implementieren würde, was Sie tun ... aber ich vermisse immer noch, wie 'incomingConnection() 'heißt .... –

+0

@code_fodder der Link zum Tutorial wird in der allerersten Zeile erwähnt . Ich hatte/hatte den gleichen Kampf über "incomingConnection()". AFAIU Diese Funktion ist eine überschriebene Funktion (d. H. Eine virtuelle Funktion), die ähnliche Mechanismen wie eine überschriebene 'run()' Funktion hat, wenn Sie eine Klasse von 'QThread' erben.Leider hatte ich nicht die Zeit, genauer hinzusehen – user3085931

Antwort

1

In Ihrem Haupt-Code:

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(); 

Dann wird Ihr wirelessnet Klasse-Header:

class WirelessNet : public QTcpServer 
{ 
    Q_OBJECT 

public: 
    WirelessNet(QObject *parent = 0); 

protected: 
    void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE; 

public slots: 
    void startWifi(); 
}; 

Dann Körper Ihre wirelessnet Klasse:

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()); 
} 

note dieses Beispiel-Code, Ich habe es direkt in den Stack-Überlauf geschrieben, es ist nicht Co gewesen mpiled, also gibt es wohl einige Fehler :) Es gibt einige wichtige Punkte, die ich kommentiert habe, wo du vielleicht bei deinem ursprünglichen Versuch schief gegangen bist.

+0

Ich verstehe ehrlich gesagt nicht dieses Verhalten. Jetzt ist der Körper von 'WirelessNet()' leer und 'startWifi()' ist wie in Ihrem Code erwähnt. Vorher war es umgekehrt: 'startWifi()' war praktisch leer und der Konstruktor 'WirelessNet()' lauschte(). Es funktioniert jetzt und ich bin damit zufrieden, aber würde es Ihnen etwas ausmachen, mir den Unterschied zu erklären? – user3085931

+1

Die Sache hier ist (ich versuchte, in den Kommentaren zu erklären, aber schlecht), wenn Sie Ihr WLAN-Objekt erstellen, wird der c'tor (z. B. WirelessNet :: WirelessNet()) aufgerufen. Alles, was Sie hier erstellen, wird in dem Thread erstellt, der WLAN erstellt hat - also der Haupt-Thread. Also habe ich Ihren Anruf abgemeldet. Dann, nachdem du wifi.moveToThread (...) gemacht hast; und starte dann den thread (thread-> start()) dein objekt wifi lebt nun im neuen thread (und thread wird auch zu seinem elternteil). Da wir das QThread :: started() -Signal mit dem WirelessNet :: startWifi() - Slot verbunden haben, gibt es beim Starten des Threads das Signal und ... –

+1

... startWifi() wird ausgeführt. Hinweis: Alles, was in dieser Funktion/diesem Slot ausgeführt wird, wird jetzt im neuen Thread ausgeführt. Also habe ich deine listen() Funktion hierher verschoben. Dort wo andere kleinere Probleme mit Ihrer ursprünglichen Einrichtung (wie das Zuordnen eines Elternteils) einen anderen Blick auf meine Kommentare werfen, habe ich nur kommentiert, wo etwas Interessantes vor sich geht. Ich kann nicht 100% sagen, warum das Bewegen im Thread zuhören funktioniert, weil ich nicht weiß, was ich höre ... aber wenn es irgendwelche Objekte erzeugt, wären sie am falschen Ort (Thread)! –