Karthik Poojary
Karthik Poojary

Reputation: 53

How to receive proper UDP packet in QT?

I am trying write a QT program to receive UDP packet.I am trying to receive from Packet Sender software This is my code

    socket = new QUdpSocket(this);
    bool result =  socket->bind(QHostAddress("150.100.50.88"),45454);
    qDebug() << result;
    if(result)
    {
        qDebug << "PASS";
    }
    else
    {
        qDebug << "FAIL";
    }
    processPendingDatagrams();
    connect(socket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()),Qt::QueuedConnection);


    void UDP::processPendingDatagrams() 
    {
        QHostAddress sender;
        u_int16_t port;
        while (socket->hasPendingDatagrams())
        {
            QByteArray datagram;
            datagram.resize(socket->pendingDatagramSize());
            socket->readDatagram(datagram.data(),datagram.size(),&sender,&port);
           qDebug() <<"Message From :: " << sender.toString();
           qDebug() <<"Port From :: "<< port;
           qDebug() <<"Message :: " << datagram;    
       } //! [2] 
   }

UDP.h:

 class UDP : public QObject 
 {
 Q_OBJECT public:
 explicit UDP(QObject *parent = 0);

 signals:

 public slots:
 void SendDatagram(u_int8_t,u_int8_t,u_int8_t);

 private slots:
 void processPendingDatagrams();

 private :
 QUdpSocket *socket; 
 };

The readReady signal and corresponding slot are not working . I can see the packets in Wireshark. If a I try receive the packets in continuously in a loop I am able see the datagrams.What can be the reason for signals and Slots for not working.Sending operation is working well.

Upvotes: 5

Views: 16385

Answers (3)

Bersan
Bersan

Reputation: 3443

@Gabriel answer did't work for me because it's using the old connect syntax. I updated it to the following (Qt 6):

// udpclient.h

#ifndef UDPCLIENT_H
#define UDPCLIENT_H
#include <QObject>
#include <QUdpSocket>

class UdpClient: public QObject
{
    Q_OBJECT

public:
    explicit UdpClient(QObject *parent);
    void initSocket();

private:
    void processPendingDatagrams();
    QUdpSocket *socket=nullptr;

};

#endif // UDPCLIENT_H
// udpclient.cpp

#include "udpclient.h"

UdpClient::UdpClient(QObject *parent) : QObject(parent) {
}

void UdpClient::initSocket()
{
    socket = new QUdpSocket(this);
    bool result =  socket->bind(QHostAddress::AnyIPv4, 4999);
    if(result)
    {
        qDebug() << "Socket PASS";
    }
    else
    {
        qDebug() << "Socket FAIL";
    }

    processPendingDatagrams();
    connect(socket, &QUdpSocket::readyRead, this, &UdpClient::processPendingDatagrams);

}

void UdpClient::processPendingDatagrams()
{
    qDebug() << "in !";
    QHostAddress sender;
    quint16 port;
    while (socket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(socket->pendingDatagramSize());
        socket->readDatagram(datagram.data(),datagram.size(),&sender,&port);
        qDebug() <<"Message From :: " << sender.toString();
        qDebug() <<"Port From :: "<< port;
        qDebug() <<"Message :: " << datagram;
    }
}

It can be used in a function or main() as:

auto udpClient = new UdpClient(0);
udpClient->initSocket();

Upvotes: 0

LimeAndConconut
LimeAndConconut

Reputation: 49

In my case this did not work, because there was always a "dummy" datagram left somewhere in memory, even if hasPendingDatagrams() returned false, I had to call readDatagram one more time to let my program receive newer datagrams. My answer is here anyways https://stackoverflow.com/a/74056997/11414500 Good luck!

Upvotes: 0

Gabrielle de Grimouard
Gabrielle de Grimouard

Reputation: 2005

This code work for me. Try it please.

.pro:

#-------------------------------------------------
#
# Project created by QtCreator 2017-03-10T11:44:19
#
#-------------------------------------------------

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = test
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

mainwindow.cpp:

#include "mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    socket = new QUdpSocket(this);
        bool result =  socket->bind(QHostAddress::AnyIPv4, 45454);
        qDebug() << result;
        if(result)
        {
            qDebug() << "PASS";
        }
        else
        {
            qDebug() << "FAIL";
        }
        processPendingDatagrams();
        connect(socket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()),Qt::QueuedConnection);
}

MainWindow::~MainWindow()
{
}

void MainWindow::processPendingDatagrams()
 {
    qDebug() << "in !";
    QHostAddress sender;
    u_int16_t port;
    while (socket->hasPendingDatagrams())
    {
         QByteArray datagram;
         datagram.resize(socket->pendingDatagramSize());
         socket->readDatagram(datagram.data(),datagram.size(),&sender,&port);
        qDebug() <<"Message From :: " << sender.toString();
        qDebug() <<"Port From :: "<< port;
        qDebug() <<"Message :: " << datagram;
    }
}

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QUdpSocket>


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void processPendingDatagrams();
private:
    QUdpSocket *socket = nullptr;
};

#endif // MAINWINDOW_H

main.cpp:

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

tried with netcat with the command:

 netcat -u 127.0.0.1 45454

once you ran the command, just type anything and press return.

Upvotes: 7

Related Questions