PDA

View Full Version : QtNetwork: Why don't I detect incomming connections ? (incomingConnection() is never



QtExchange
24th March 2016, 11:38
I sticked to the tutorial about threaded qt-networking (which is here: http://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html), I made some minor changes and integrated it into my main program. However incomingConnection() never gets executed, on the other hand the client is able to connect. Since I'd like to work with incomingConnection() it became obsolete to work with the SIGNAL(newConnection()) but even this isn't working.

Somebody knows what's going wrong?

Here my .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;

};

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

here the excerpt out of my main program, where it is initiated (by the way it doesn't matter if I leave out moveToThread()):


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

Even this has no influence if I add these lines after the initalization of wifi:


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

In other words "incomming" is never printed out, and so I'm not able to work on. Has anyone an idea, this is pretty much 1:1 the code from the tutorial that's what confuses me.

Kind Regards

anda_skoa
24th March 2016, 11:58
here the excerpt out of my main program, where it is initiated (by the way it doesn't matter if I leave out moveToThread()):

That is quite understandable as it would move the object to the thread it is already on, i.e. no change.

Given that WirelessGloveThread::run() is probably actually WirelessNetThread::run() and that wifi is hopefully actually a pointer, I wonder how much else of that is not actually your code.

Can we at least assume that your actual code is reporting "true" for isListening()?
Is the wifi object an object of the main thread?
Is the application's event loop running?
If you connect to the newConnection() signal, is the slot invoked?

Cheers,
_

QtExchange
24th March 2016, 12:13
Of course you were right, I had to type it by hand since the working machine has no internet connection, so these were just typos.

And yes everytime the line "is listenning 1" is printed out, so isListenning is True.

the eventloop should be running (I'm not sure how to check this), however when adding an extra QEventLoop + exec() as mentioned in the post it doesn't change the situation either

anda_skoa
24th March 2016, 16:44
And does the signal get emitted?

Cheers,
_

QtExchange
24th March 2016, 22:47
Alternatively I tried to catch the SIGNAL(newConnection()) instead of the overridden incommingConnection() on server side. But as mentioned above this signal never gets fired or at least not processed.

On client side I surprisingly have absolutely no problem connecting to this server, after I executed its listen() - but still no reaction on server side

jefftee
25th March 2016, 01:59
Somebody knows what's going wrong?
My advice? Learn to walk before you try to run. Qt's networking classes are asynchronous and don't require multi-threading to work properly.

If you've read how to properly do threading in Qt, people typically use one of the 1) moveToThread method or 2) subclass QThread and implement your code in the QThread::run() method. You seem to want to do both, which I think demonstrates a lack of understanding regarding how to properly do multi-threading in Qt.

Scrap the threading altogether and start with a simple QTcpServer that can accept incoming connections, handle reading/writing data to the socket, and handle client disconnects, etc. Do that first before you try to introduce multiple threads or add any other features to your application.

Good luck.

anda_skoa
25th March 2016, 10:12
Alternatively I tried to catch the SIGNAL(newConnection()) instead of the overridden incommingConnection() on server side. But as mentioned above this signal never gets fired or at least not processed.

Ah, sorry, didn't see that.



On client side I surprisingly have absolutely no problem connecting to this server, after I executed its listen() - but still no reaction on server side
Hmm, maybe the client is connecting to something else?

Cheers,
_

jefftee
25th March 2016, 21:57
In your original post, you show a run() method for your thread that does not contain a message loop and will exit almost immediately after your thread is started. The default QThread::run() runs a message loop. If you write your thread to persist and continue to run, you should execute the base class QThread::run() in your subclassed run() method or just simply call exec() in your run() method.

Without this, your thread will start and end almost instantaneously, which I'm sure is not what you intended.

QtExchange
30th March 2016, 08:13
Please pardon my late reply for I have not been at the desk during the holidays.



Hmm, maybe the client is connecting to something else?


It's a wireless network where there is only 1 host & 1 client. The client is not able to connect if the host hasn't reached the line listen()


My advice? Learn to walk before you try to run.

That's why I stick to the tutorial made directly by Qt, how does one learn the very lowest instance of a teaching unit if even this ain't running.


In your original post, you show a run() method for your thread that does not contain a message loop and will exit almost immediately after your thread is started. The default QThread::run() runs a message loop. If you write your thread to persist and continue to run, you should execute the base class QThread::run() in your subclassed run() method or just simply call exec() in your run() method.

Without this, your thread will start and end almost instantaneously, which I'm sure is not what you intended.

This might be true. However I don't even get to the point where this thread is created - which is my actual problem mentioned in the top post. As stated incomingConnection(), where this thread first is created, is never fired.

anda_skoa
30th March 2016, 08:37
It's a wireless network where there is only 1 host & 1 client. The client ain't able to connect if the host hasn't reached the line listen()

I did not mean another host, I meant another program.
If you have more than one interface, say actual network and loopback and another program is listening on the same port on loopback, your program will still be able to listen on the wifi network interface, but the client might connect to the server listening on loopback.

Cheers,
_

QtExchange
30th March 2016, 09:08
I did not mean another host, I meant another program.
If you have more than one interface, say actual network and loopback and another program is listening on the same port on loopback, your program will still be able to listen on the wifi network interface, but the client might connect to the server listening on loopback.

Well it is only working after listen(). In general I don't consider this as a problem, since I switched from windows libraries to Qt for networking and kept the settings (ports & addresses). With these libraries everything worked like charm, but now I switched to Qt for ensuring mulitple platform compatibility.

jefftee
31st March 2016, 03:01
Why don't you post your entire project so we can see the code in its entirety or alternatively a compilable example that demonstrates the problem?

QtExchange
31st March 2016, 07:44
It is working now and the reason is the listen() was in the wrong position and you need an additional Signal/Slot connection from main program to the network extension as following:

the main program gets changed like this:


wifi= new WirelessNet(0);
QThread *thread = new QThread;
wifi->moveToThread(thread);
connect(thread,SIGNAL(started()), wifi,SLOT(initWifi()));
thread->start();

the constructor of WirelessNet is now empty, therefore it gets a new public slot function:


void WirelessNet::initWifi()
{
listen(QHostAddress::Any, 5220);
}

And that's the trick.

If one is creating a WirelessNet-Instance, starts listenting inside the constructor but first then uses the movetoThread(), the connection is lost.

Concluding in one sentence: First move to the right thread and afterwards start listening

Thanks for your help. Let me tell you I hate the official Qt-""Tutorials""

anda_skoa
31st March 2016, 09:03
If one is creating a WirelessNet-Instance, starts listenting inside the constructor but first then uses the movetoThread(), the connection is lost.

Ah, good to know.



Thanks for your help. Let me tell you I hate the official Qt-""Tutorials""
Well, the example you based on is actually good, it doesn't do anything weird like moving the server into another thread.
Its goal is to demonstrate how to handle client connections in separate threads and I think it does that quite well.

Cheers,
_

jefftee
31st March 2016, 19:08
If you've read how to properly do threading in Qt, people typically use one of the 1) moveToThread method or 2) subclass QThread and implement your code in the QThread::run() method. You seem to want to do both, which I think demonstrates a lack of understanding regarding how to properly do multi-threading in Qt.
Can you explain why you are opposed to following the best practices when it comes to multi-threading in Qt? Subclassing QThread *and* using the moveToThread approach is not something that you'll find in any (working) example.

Glad that you have it working for now, but I would still personally adopt one of the QThread subclass approach or the moveToThread approach, not both.