Results 1 to 13 of 13

Thread: QUdpSocket running in QThread - change port

  1. #1
    Join Date
    Mar 2020
    Posts
    8
    Thanks
    1
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default QUdpSocket running in QThread - change port

    Hi everyone!
    A simple question, but cannot find any solution.

    I have a class:
    Qt Code:
    1. class Test: public QThread
    2. {
    3. Q_OBJECT
    4. public:
    5. Test();
    6. int port; //An UDP port to bind to
    7. void run() override; // creates, assigns an QUdpSocket object to the so variable, and binds it to some initial port.
    8.  
    9. public slots:
    10. void reconnect(); // Should bind socket to some other port, than the one bound while initializing.
    11. void receive(); // Called to receive datagram. Works fine.
    12. };
    To copy to clipboard, switch view to plain text mode 
    The run() function looks like (simplyfied):
    Qt Code:
    1. void Test::run()
    2. {
    3. so = new QUdpSocket();
    4. so->bind(port);
    5. this->exec();
    6. so->deleteLater();
    7. }
    To copy to clipboard, switch view to plain text mode 
    As a result, the QUdpSocket *so lives in its own thread.
    Is there some way to run reconnect() slot inside this same thread, where the run() function and UdpSocket *so live in? Otherwise the bind to another port isn't allowed:
    QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
    QObject: Cannot create children for a parent that is in a different thread.
    I've tried a lot. Always ending with running the SLOT reconnect() inside the SIGNALs thread.

    Please, give me any suggestion, because I stuck out of ideas - since days now.

  2. #2
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    866
    Thanks
    69
    Thanked 58 Times in 56 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    Hi,

    You have to use the SIGNAL/SLOT mechanism. Just connect a SIGNAL to "reconnect" method and then use the "emit mySignal()".
    You also can use the "QMetaObject::invokeMethod" function.
    Òscar Llarch i Galán

  3. #3
    Join Date
    Mar 2020
    Posts
    8
    Thanks
    1
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    First, thank you, for your time and attention!

    Using of SIGNAL/SLOT pair works for the receive() function, as the signal is emitted by an object QUdpSocket *so created inside QThread's run() function.

    But it definitely doesn't apply to a SIGNAL from any other source. The SLOT reconnect() inherits in this cases affinity to the sender's thread - no matter if used Qt::QueuedConnection (which should leve it to the Qthread's event loop started by exec()), or Qt::DirectConnection. This totally ruins my whole experience with the QThreads.
    I can provide a sample of code, if someone had time and patience to look at ma "headache" it on his own.

    QMetaObject::invokeMethod is something, I've never used and now have obviously to delve into.

    Thanks!

  4. #4
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    866
    Thanks
    69
    Thanked 58 Times in 56 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    Hi,

    Where dou you call "reconnect()" ?
    Òscar Llarch i Galán

  5. #5
    Join Date
    Mar 2020
    Posts
    8
    Thanks
    1
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    From the main Widget if you mean the SIGNAL source. Please, let me prepare and upload the simple example, so you can see all clearly.

  6. #6
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    866
    Thanks
    69
    Thanked 58 Times in 56 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    Hi,

    And how do you call it?
    Òscar Llarch i Galán

  7. #7
    Join Date
    Mar 2020
    Posts
    8
    Thanks
    1
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    In the main Widget, I've connected a SIGNAL from QPushButton on the GUI to the SLOT reconnect() from the QThread based class.
    Just as below:
    Qt Code:
    1. connect(ui->pushButton, SIGNAL(released()), udpTest, SLOT(reconnect()), Qt::QueuedConnection);
    To copy to clipboard, switch view to plain text mode 
    I made all so simple, as it only was be possible, leaving just the bare minimum, to still work and get the error/warnings.
    You can build and run this program.
    I added a qDebug() to every operation, so you can read the thread's IDs of any called function.

    MainWidget.png

    Using netcat one can send some data to the UDP port 1111. Then the debug output should look something like:

    Qt Code:
    1. Main Loop() thread ID: 0x888
    2. run() thread ID: 0x140c
    3. receive() thread ID: 0x140c
    4. reconnect() thread ID: 0x888
    5. QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
    6. QObject: Cannot create children for a parent that is in a different thread.
    7. (Parent is QUdpSocket(0x6441a0), parent's thread is UDP(0x6448a0), current thread is QThread(0x3193c0)
    To copy to clipboard, switch view to plain text mode 
    Attached Files Attached Files

  8. #8
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    866
    Thanks
    69
    Thanked 58 Times in 56 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    Hi,

    Finally I found the problem. That is that you are creating the UDP Socket when the thread is not really runnig yet.
    Check the modifications.
    Attached Files Attached Files
    Òscar Llarch i Galán

  9. The following user says thank you to ^NyAw^ for this useful post:

    sanji (4th March 2020)

  10. #9
    Join Date
    Mar 2020
    Posts
    8
    Thanks
    1
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    A huuuge thanks to you, for your rapid help!

    But to understand and not just copy your solution, I need to ask, what did you mean with:
    That is that you are creating the UDP Socket when the thread is not really runnig yet.
    I'm creating the UDP socket inside the run() method, after running of start() method on the QThread object. And this method has already other thread ID than the main thread.
    So how can it be possible, that the thread is not really running yet?

  11. #10
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    866
    Thanks
    69
    Thanked 58 Times in 56 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    Hi,

    I don't remeber where I readed it but basically the OS will start the thread after calling "start". Maye into Qt Threads documentation.

    So, a good way of doing it is waiting the "started" SIGNAL emited by the thread.

    You get a different thread ID because it is assigned on "start()" call but as I noticed, the thread is not really running. Sometimes people are confused about the QThread inherited object and the thread where its execution is done. One thing is an object, and the other is a OS thread.

    Hope it helps.
    Òscar Llarch i Galán

  12. #11
    Join Date
    Mar 2020
    Posts
    8
    Thanks
    1
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    Sad news.
    Your program works, in fact, without any errors. But after some tests, looking at the qDebug output I noticed:

    20:52:42: Starte z:\build-UDPTest-Desktop_Qt_5_14_1_MinGW_64_bit-Debug\UDPTest.exe ...
    Main Loop() thread ID: 0x73c
    run() thread ID: 0x2fc
    reconnect() thread ID: 0x73c
    receive() thread ID: 0x73c
    reconnect() thread ID: 0x73c
    So all the SLOTS are running in the main thread 0x73c, while the run() method runs inside of 0x2fc.

    I've reorganized the reconnect() SLOT a little, to run bind() only once at first run, but it has no effect on the thread assignment. It's just, how the method should finally look like. (And the previous debug output comes from your "RAW" version.)

    Qt Code:
    1. void UDP::reconnect()
    2. {
    3. //If socket exists do not create again
    4. if (so == 0)
    5. {
    6. so = new QUdpSocket(this);
    7. connect(so, SIGNAL(readyRead()), this, SLOT(receive()), Qt::DirectConnection);
    8. so->bind(1111);
    9. } else {
    10. so->disconnectFromHost();
    11. so->bind(1112);
    12. }
    13.  
    14. qDebug() << "reconnect() thread ID: " << QThread::currentThreadId();
    15. Qt::HANDLE qThreadId = QThread::currentThreadId();
    16. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by sanji; 4th March 2020 at 20:17.

  13. #12
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    866
    Thanks
    69
    Thanked 58 Times in 56 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    Hi,

    Sorry for my words ... "Fucking deleteLater !!!".

    I have tryied another approach on the way I use to to this tasks. It now works but you cannot call "deleteLater" as you are telling the EvenLoop to delete the object as soon as possible.
    Attached Files Attached Files
    Òscar Llarch i Galán

  14. #13
    Join Date
    Mar 2020
    Posts
    8
    Thanks
    1
    Qt products
    Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QUdpSocket running in QThread - change port

    For the moment I managed only to see if all is in the same thread. Had no time to delve into code, so have no questions yet. Just big thanks, as it, indeed works!

    Qt Code:
    1. 08:11:19: Starte z:\build-UDPTest-Desktop_Qt_5_14_1_MinGW_64_bit-Debug\UDPTest.exe ...
    2. Main Loop() thread ID: 0xe38
    3. run() thread ID: 0x15e4
    4. receive() thread ID: 0x15e4
    5. reconnect() thread ID: 0x15e4
    6. 08:11:22: z:\build-UDPTest-Desktop
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. QUdpSocket change port
    By sanji in forum Qt Programming
    Replies: 0
    Last Post: 1st March 2020, 22:22
  2. Replies: 1
    Last Post: 4th October 2012, 14:49
  3. Setting Source Port for QUdpSocket
    By MSUdom5 in forum Qt Programming
    Replies: 0
    Last Post: 12th April 2012, 13:15
  4. Specify source port on QUdpSocket packet
    By gio0166 in forum Qt Programming
    Replies: 3
    Last Post: 4th October 2011, 02:14
  5. QUdpSocket -- Rebinding with Different Port Numbers
    By swamyonline in forum Qt Programming
    Replies: 0
    Last Post: 22nd January 2009, 13:39

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.