UDP packets received only the first time.
-
Hi All, i'm having this weird problem, i only receive the udp packets the first time i send them, all after that aren't shown anymore.
Here is what i have, can you please help me figure out what the problem is ?:
receiver.h
#ifndef RECEIVER_HPP #define RECEIVER_HPP #include <QtCore/QObject> class QUdpSocket; /** * The Receiver class handles the processing of the incoming UDP datagrams. * It uses a QUdpSocket to retrieve the datagrams and makes the content of * the datagram available to the UI via the 'status' property. */ class Receiver : public QObject { Q_OBJECT // The property that makes the content of a received datagram available to the UI Q_PROPERTY(QString status READ status NOTIFY statusChanged) public: void initSocket(); Receiver(QObject *parent = 0); Q_SIGNALS: // The change notification signal of the status property void statusChanged(); private slots: void processPendingDatagrams(); private Q_SLOTS: // This method is called whenever a new datagram arrived on the socket // void processPendingDatagrams(); private: // The accessor method of the status property QString status() const; // The UDP socket object QUdpSocket *m_udpSocket; // The content of the received datagram QString m_status; }; #endif
receiver.cpp
#include "receiver.h" #include <QThread> #include <QtNetwork/QUdpSocket> Receiver::Receiver(QObject *parent) : QObject(parent) { /** * Initialize the 'status' property with no data, it won't * be shown in the UI until the first datagram arrives. */ m_status = "--"; m_udpSocket = new QUdpSocket(this); m_udpSocket->bind(QHostAddress::AnyIPv4, 4210); processPendingDatagrams(); connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()), Qt::QueuedConnection); /* // Create a new UDP socket and bind it against port 45454 m_udpSocket = new QUdpSocket(this); if(m_udpSocket->bind(QHostAddress::LocalHost, 4210)) qDebug() << "Bind true on port" << 4210; else qDebug() << "Bind super failed"; * Create signal/slot connection to invoke processPendingDatagrams() whenever * a new datagram is received by the socket. // connect(m_udpSocket, SIGNAL(readyRead()), this, // SLOT(processPendingDatagrams()));*/ } void Receiver::initSocket(){ QByteArray Data; Data.append("Hello from UDP"); // Sends the datagram datagram // to the host address and at port. // qint64 QUdpSocket::writeDatagram(const QByteArray & datagram, // const QHostAddress & host, quint16 port) // m_udpSocket->writeDatagram(Data, QHostAddress::LocalHost, 4210); } void Receiver::processPendingDatagrams() { // Now read all available datagrams from the socket while (m_udpSocket->hasPendingDatagrams()) { // Create a temporary buffer ... QByteArray datagram; QHostAddress sender; quint16 senderPort; qDebug() << "2 "; // ... with the size of the received datagram ... datagram.resize(m_udpSocket->pendingDatagramSize()); // ... and copy over the received datagram into that buffer. m_udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); // Update the 'status' property with the content of the received datagram // m_status = tr("%1").arg(datagram.data()); qDebug() << "Message from: " << sender.toString(); qDebug() << "Message port: " << senderPort; qDebug() << "Message: " << datagram; // emit statusChanged(); } } QString Receiver::status() const { return m_status; }
main.cpp
#include <QGuiApplication> #include <QQmlApplicationEngine> #include<QDebug> #include <QQmlEngine> #include <QQmlComponent> #include <QQmlProperty> #include "receiver.h" #include <QQmlContext> #include "touchitem.h" #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // QCoreApplication::setAttribute(Qt:QT_QPA_EGLFS_HIDECURSOR, true); QCoreApplication::setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true); QGuiApplication app(argc, argv); app.setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true); QQmlApplicationEngine engine; QObject::connect(&app, &QGuiApplication::aboutToQuit, &thread, &Thread::stop); engine.rootContext()->setContextProperty("applicationDirPath", QGuiApplication::applicationDirPath()); const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); QString test = ""; Receiver receiver ; receiver.initSocket(); return app.exec(); }
-
I don't have time to help your specific example (sorry). However, I'd suggest looking at the functional example projects in Qt Creator. Look for something like "fortune server" and "fortune client" there's a couple examples that should get you right on track.
-
@Eli_a_n said in UDP packets received only the first time.:
i only receive the udp packets the first time i send them, all after that aren't shown anymore
What does this mean exactly? Do you stop and start your app and then it does not work?
-
@jsulm Hi,
So, i start the app, i send an udp packet from another terminal in the local network, i receive and display it in qt, everything is fine so far. With the app still running, and without changing anything, i send the second packet from the same terminal in the local network and i don't receive it (or it just doesn't display it) in qt.
It's absolutely weird.
What are your thoughts?
-
processPendingDatagrams(); connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()), Qt::QueuedConnection);
Probably irrelevant, but I'd get rid of the first
processPendingDatagrams();
, outside of theconnect(SIGNAL(readyRead()))
, just in case it influences what you see. There is no need for it in your test problem, is there?m_udpSocket->bind(QHostAddress::AnyIPv4, 4210);
bind()
returns abool
. If you don't c heck it, maybe the whole binding isn't working....void QAbstractSocket::errorOccurred(QAbstractSocket::SocketError socketError)
: if you don't slot this signal, how would you know if there is some error?These are the sort of things I would do if developing and I had a problem.
-
@JonB thanks for the heads up
Here is what i did:
Receiver::Receiver(QObject *parent) : QObject(parent) { m_status = "--"; m_udpSocket = new QUdpSocket(this); if(m_udpSocket->bind(QHostAddress::AnyIPv4, 4210)) qDebug() << "Bind succesfull on port 4210" ; else qDebug() << "Bind failed on port 4210"; connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()), Qt::QueuedConnection); connect(m_udpSocket, SIGNAL(disconnected()), this, SLOT(Disconnected())); connect(m_udpSocket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), [=](QAbstractSocket::SocketError socketError){ qDebug() << "socket error " << socketError; }); } void Receiver::processPendingDatagrams() { while (m_udpSocket->hasPendingDatagrams()) { QByteArray datagram; QHostAddress sender; quint16 senderPort; qDebug() << "2 "; datagram.resize(m_udpSocket->pendingDatagramSize()); m_udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); qDebug() << "Message from: " << sender.toString(); qDebug() << "Message port: " << senderPort; qDebug() << "Message: " << datagram; } } void Receiver::ReceiveData () { qDebug() <<"Socket received data..."; } void Receiver::Disconnected () { qDebug() <<"Socket got disconnected..."; } void Receiver::Error (QAbstractSocket::SocketError error) { qDebug() <<"Socket error " << error; }
but i get o disconnect message nor an error message:
pi@raspberrypi:~/RTCs/bin $ ./RTCs QML debugging is enabled. Only use this in a safe environment. Bind succesfull on port 4210 Message from: "192.168.68.111" Message port: 52848 Message: "test\r\n"
-
Hi,
Did you check the examples linked in the details of the QUdpSocket class ?
Compare them to your client and server code to spot the differences.
On a side note, you should move all your connection to the new style so you won't have any runtime surprises.
-
@Eli_a_n said in UDP packets received only the first time.:
i only receive the udp packets the first time i send them, all after that aren't shown anymore.
One thing. I've seen a fair amount of user questions in this forum. If I come over to your place and find that actually you are only sending one packet, will you give me $5? :) Please verify multiple packets really are being sent...!
-
@JonB :)) that would be funny but i'm actually sending the packets using software called UDP - Sender/Reciever from Microsoft Store. To make sure that i have no problem with firewall or anything like that i made a simple app in python and i'm getting all the packets just fine there. So there is a problem with the QT app.
I will try to investigate some more.
By the way, not sure if it makes any difference but i'm running the QT app on raspberry pi.
Regards
-
Not sure i'm loading the class correctly.
in my main.cpp i do :
Receiver *rcv = new Receiver(); rcv->initSocket();
where initSocket is:
void Receiver::initSocket(){ QByteArray Data; Data.append("Hello from UDP"); m_udpSocket = new QUdpSocket(this); if(m_udpSocket->bind(QHostAddress::AnyIPv4, 4210)) qDebug() << "Bind succesfull on port 4210" ; else qDebug() << "Bind failed on port 4210"; connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()), Qt::QueuedConnection); connect(m_udpSocket, SIGNAL(disconnected()), this, SLOT(Disconnected())); connect(m_udpSocket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), [=](QAbstractSocket::SocketError socketError){ qDebug() << "socket error " << socketError; }); // Sends the datagram datagram // to the host address and at port. // qint64 QUdpSocket::writeDatagram(const QByteArray & datagram, // const QHostAddress & host, quint16 port) // m_udpSocket->writeDatagram(Data, QHostAddress::LocalHost, 4210); }
shoud i start the Receiver class in a thread or something?
using the debuger, after i receive the first packet, using the "step over" i end up back in the main.cpp at the line :
return app.exec();Is this normal ?
-
Please simply use the examples from Qt to see if it works for you as @SGaist already told you. There we know the code exactly and we know they're working fine for us. We don't know your program and you don't provide a minimal, compilable example so we can't see what else you're doing.
See e.g. https://doc.qt.io/qt-5/qtnetwork-broadcastreceiver-example.html and https://doc.qt.io/qt-5/qtnetwork-broadcastsender-example.html
-
@Christian-Ehrlicher Hi, what do you mean? in my initial post i provided the main.cpp and both full receiver files, what else would you need? Anyway,
I loaded the broadcast receiver project you suggested and currently i have the following cases:
-
Launching from one terminal the broadcast receiver app you suggested and from another terminal using netcat -u 127.0.0.1 45454 and netcat -u 192.168.68.107 45454 (which is the IP of my raspberry pi on the local network) i get all the messages that i'm sending
-
without changing anything in the case 1 above, i'm sending the packets from:
- Ubuntu terminal - netcat -u 192.168.68.107 45454
- Windows UDP - Sender/receiver application
- Packet sender application on windows
From none of the apps listed above manage to receive the packets
-
Closing the broadcast receiver app and opening a simple python udp receiver i can receive the packets from all mentioned at case 2
-
Closing the python receiver app and opening my initial application i can receive only the first packet sent.
Any thoughts ?
Regards
-
-
OK, so i don't know exactly why but I got it working.
I believe that the following were the problems:
m_udpSocket->bind(QHostAddress::AnyIPv4, 4210) **instead of** udpSocket->bind(45454, QUdpSocket::ShareAddress); as mentioned in the broadcast receiver example
connect(m_udpSocket, &QUdpSocket::readyRead, this, &Receiver::processPendingDatagrams); **instead of** connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(ReceiveData()), Qt::QueuedConnection); what i used in my initial application when posting for help
while (m_udpSocket->hasPendingDatagrams()) { datagram.resize(int(m_udpSocket->pendingDatagramSize())); m_udpSocket->readDatagram(datagram.data(), datagram.size()); qDebug() << "Message: " << datagram.constData(); } **instead of** while (m_udpSocket->hasPendingDatagrams()) { QByteArray datagram; QHostAddress sender; quint16 senderPort; qDebug() << "2 "; datagram.resize(m_udpSocket->pendingDatagramSize()); m_udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); qDebug() << "Message from: " << sender.toString(); qDebug() << "Message port: " << senderPort; qDebug() << "Message: " << **datagram;** //as per my initial program }
Thank you all for all your involvement and support
Regards
Elian N.