QUdpSocket Data Transmission in LAN



  • Hi everyone,

    I am currently trying to send data from computer A to computer B in a LAN. Both the sender and receiver are running QT, using QUdpSocket to send and receive data. Computer A could successfully send the data to computer B as I have tested using MATLAB(on the receiver) to check the received data. However, I could not receive the data using QT.
    I have attached the portion of code for sender and receiver that is responsible for data transmission.

    Computer A (sender, IP:10.132.12.59)
    @
    void MyUDP::HelloUDP()
    {
    QByteArray msg("Hello");
    if( socket->writeDatagram(Data.data(), Data.size(), QHostAddress("10.132.12.73"), 9090) == -1)
    qDebug() << "Data sending failed!";
    else
    qDebug() << Data.size() << "bytes data sent successfully";
    }
    @

    Computer B (receiver, IP:10.132.12.73)
    main.cpp
    @
    #include <QCoreApplication>
    #include "myudp.h"

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);
    MyUDP client;
    return a.exec();
    }@

    myudp.cpp
    @
    #include <QCoreApplication>
    #include "myudp.h"

    MyUDP::MyUDP(QObject *parent) :
    QObject(parent)
    {
    socket = new QUdpSocket(this);
    socket->bind(QHostAddress::LocalHost, 9090);
    connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
    }

    void::readyRead()
    {
    QByteArray buffer;
    buffer.resize(socket->pendingDatagramSize());

    QHostAddress sender;
    quint16 senderPort;
    
    socket->readDatagram(buffer.data(), buffer.size(),
                         &sender, &senderPort);
    
    qDebug() << "Message from: " << sender.toString();
    qDebug() << "Message port: " << senderPort;
    qDebug() << "Message: " << buffer;
    

    }
    @

    Note that on the receiver, I have also tried to bind the address to QHostAddress::Any and from the sender, I broadcasted the message but nothing works. I believe the ReadyRead() signal of the socket is not triggered here. I am not sure what I am doing wrong here. Please guide me. Thanks in advance.



  • Have you try debug receiver side?
    Also Wireshark will help you to see what happening in the network.



  • Yes I have tried debugging. But since it just enters the loop and wait for any data to be received, I could not debug much. Which means there were no signal triggered even when data is received. I have checked through WireShark on the receiver computer as well. The data is indeed received.

    I also tried to put a timer in the receiver computer to manually check if there is any pending datagram using the function "hasPendingDatagram". But it always return false. Note that I have also changed the line 8 of the myudp.cpp to the following:

    @socket->bind(QHostAddress("10.132.12.73"), 9090);@



  • Your receiver needs to bind to the external IP address of the host machine, not LocalHost (which is the internal loopback). Using QHostAddress::Any will achieve this.

    The following is a complete working example of sending and receiving a UDP datagram (a seperate Qt project/app for each) I wrote for teaching purposes a while back, I've just tested it again and it works fine with Qt4.8 and Qt5.2. Hopefully this will help you track down your issue:

    Sender

    UDPSender.pro
    @
    QT += core gui network

    TARGET = UDPSender
    TEMPLATE = app

    SOURCES += main.cpp
    widget.cpp

    HEADERS += widget.h
    @

    widget.h
    @
    #ifndef WIDGET_H
    #define WIDGET_H

    #include <QtGui/QWidget>

    class QUdpSocket;
    class QLineEdit;

    class Widget : public QWidget
    {
    Q_OBJECT

    public:
    Widget(QWidget *parent = 0);
    ~Widget();

    private:
    QUdpSocket *socket;
    QLineEdit *message;

    public slots:
    void datagramSend();
    void datagramSent();
    };

    #endif // WIDGET_H
    @

    widget.cpp
    @
    #include "widget.h"

    #include <QtNetwork>
    #include <QtGui>
    #if QT_VERSION >= 0x050000
    #include <QtWidgets>
    #endif
    #include <QDebug>

    Widget::Widget(QWidget *parent)
    : QWidget(parent)
    {
    setWindowTitle("UDP Sender");

    socket=new QUdpSocket(this);
    connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(datagramSent()));
    
    QVBoxLayout *layout=new QVBoxLayout(this);
    
    message=new QLineEdit(this);
    layout->addWidget(message);
    
    QPushButton *send=new QPushButton("&Send", this);
    connect(send, SIGNAL(clicked()), this, SLOT(datagramSend()));
    layout->addWidget(send);
    

    }

    Widget::~Widget(){}

    void Widget::datagramSend(){
    socket->writeDatagram(message->text().toAscii(), QHostAddress("10.128.6.24"), 5000);
    }

    void Widget::datagramSent(){
    qDebug() << "Datagram Sent";
    }
    @

    main.cpp
    @
    #include <QtGui/QApplication>
    #include "widget.h"

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

    return a.exec&#40;&#41;;
    

    }
    @

    Receiver

    UDPReceiver.pro
    @
    QT += core gui network

    TARGET = UDPReceiver
    TEMPLATE = app

    SOURCES += main.cpp
    widget.cpp

    HEADERS += widget.h
    @

    widget.h
    @
    #ifndef WIDGET_H
    #define WIDGET_H

    #include <QtGui/QWidget>

    class QUdpSocket;
    class QTextEdit;

    class Widget : public QWidget
    {
    Q_OBJECT

    public:
    Widget(QWidget *parent = 0);
    ~Widget();

    private:
    QUdpSocket *socket;
    QTextEdit *trace;

    public slots:
    void datagramRecv();
    };

    #endif // WIDGET_H
    @

    widget.cpp
    @
    #include "widget.h"

    #include <QtNetwork>
    #include <QtGui>
    #if QT_VERSION >= 0x050000
    #include <QtWidgets>
    #endif
    #include <QDebug>

    Widget::Widget(QWidget *parent)
    : QWidget(parent)
    {
    setWindowTitle("UDP Receiver");

    socket=new QUdpSocket(this);
    socket->bind(QHostAddress::Any, 5000);
    connect(socket, SIGNAL(readyRead()), this, SLOT(datagramRecv()));
    
    QVBoxLayout *layout=new QVBoxLayout(this);
    
    trace=new QTextEdit(this);
    trace->setReadOnly(true);
    trace->append("UDP Trace:");
    layout->addWidget(trace);
    

    }

    Widget::~Widget(){}

    void Widget::datagramRecv(){
    QByteArray data;
    QHostAddress host;
    quint16 port;

    while(socket->hasPendingDatagrams()){
        data.resize(socket->pendingDatagramSize());
        socket->readDatagram(data.data(), data.size(), &host, &port);
    
        QString portStr;
        portStr.setNum(ulong(port));
        trace->append(QString("%1:%2 -> %3").arg(host.toString(), portStr, data));
    }
    

    }
    @

    main.cpp
    @
    #include <QtGui/QApplication>
    #include "widget.h"

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

    return a.exec&#40;&#41;;
    

    }
    @

    If this doesn't work on your network, check the IP addresses you are using are correct and, as qxoz says, try Wireshark to see whats coming and going from each machine.

    Hope this helps ;o)



  • I have tried using the Wireshark to see the packets. The receiver computer is indeed receiving the packet. However, it is not coming in QT as the readyRead() signal is not emitted at all. I have also used the code given by jazzycamel. It is still not working. The IP addresses are all correct. I have checked them many times. Is there any other way that I can do this without using the readyRead() signal. Note that I am using QT 5.3 on windows 7.


  • Moderators

    Are you sure thet you have Q_OBJECT macro in your header file? Are you sure the readyRead() is marked as a SLOT?

    I have used QUdpSocket on all sorts of platforms (Linux, Windows 7 and 8, Android) and it definitely does work.



  • Yes, I am sure. I have even created a new project using the code given by jazzycamel. But it is still not working.



  • What about firewall on receiver side. Usually windows ask permission at first start of network app.



  • I am sorry, I forgot to mention that only the sender is running on windows while the receiver is running on Ubuntu. I have now tried sending the data from Ubuntu to windows, and the windows CAN receive. So, is there any settings that I have to make when transmitting the data across two different platforms?


  • Moderators

    There are no special settings required, it should work on all platforms.

    Please check the socket object for errors. Maybe the data is not being sent because the package is too big (UDP packets need to be pretty small).



  • The data is actually being sent as I have verified it using wireshark. I am still not sure what causing this problem.



  • Seeing as you can receive data from Ubuntu to Windows the code is obviously working. You say you've used Wireshark to prove the data is being sent from the Windows machine, have you used it to ensure its being received by the Linux box? Also, Wireshark only proves that the data is hitting the NIC, the OS's firewall may still be stepping in and blocking it before it reaches your application, I would definitely look at your receiving OS's network and security configuration. Do you have another (Windows) machine you could use to test this?



  • Windows to windows has no problem. I have checked but with direct LAN connection and not through a router. I think it could be as you said, the OS network/security configuration. If this is the case, how could i disable them? I am very new to Ubuntu and have no experience in it.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.