Results 1 to 9 of 9

Thread: udp broadcasting on all network interfaces

  1. #1
    Join Date
    May 2009
    Posts
    75
    Thanks
    5
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default udp broadcasting on all network interfaces

    I need to broadcast an udp packet on all network interfaces, using only QIODevice methods (QIODevice::write() and no QUDPSocket::writeDatagram()), apart from connetcing and binding.

    I also have upgraded to qt 5.6 due to qt bug #26538.

    A simplified example is as follows:
    Qt Code:
    1. class Dialog : public QDialog
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. explicit Dialog(QWidget *parent = 0);
    7. ~Dialog();
    8.  
    9. private:
    10. Ui::Dialog *ui;
    11. QUdpSocket *sock;
    12.  
    13. public slots:
    14. void onReadyRead(void);
    15. void onButtonClicked(void);
    16. };
    17.  
    18. #define USE_QIODEVICE // remove this define to use QUDPSocket methods
    19.  
    20. Dialog::Dialog(QWidget *parent) :
    21. QDialog(parent),
    22. ui(new Ui::Dialog)
    23. {
    24. ui->setupUi(this);
    25.  
    26. connect(ui->pushBtn,SIGNAL(clicked()), this, SLOT(onButtonClicked()));
    27.  
    28. qDebug() << qVersion();
    29.  
    30. sock = new QUdpSocket(this);
    31. connect(sock, &QUdpSocket::readyRead, this, &Dialog::onReadyRead);
    32.  
    33. #if !defined(USE_QIODEVICE)
    34. sock->bind();
    35. qDebug() << sock->localPort();
    36. #endif
    37. }
    38.  
    39. void Dialog::onButtonClicked(void)
    40. {
    41. QList<QNetworkInterface> list = QNetworkInterface::allInterfaces();
    42. foreach (QNetworkInterface iface, list)
    43. {
    44. QList<QNetworkAddressEntry> AEList = iface.addressEntries();
    45. foreach(QNetworkAddressEntry AE, AEList)
    46. {
    47. if(AE.broadcast().protocol() == QAbstractSocket::IPv4Protocol)
    48. {
    49. #if defined(USE_QIODEVICE)
    50. sock->bind(54366); // I have to call bind() for every interface because disconnectFromHost() unbind
    51. sock->connectToHost(AE.broadcast(), 44444); // I have to call connectToHost to make the subsequent call to write() works
    52. qDebug() << sock->localPort();
    53. sock->write("hallo");
    54. sock->disconnectFromHost(); // I have to call disconnectFromHost() otherwise the subsequent call to connectToHost() will fail
    55. #else
    56. dg = "hallo";
    57. sock->writeDatagram(dg,AE.broadcast(), 44444);
    58. #endif
    59. qDebug() << "send to" << AE.broadcast();
    60. }
    61. }
    62. }
    63. }
    64.  
    65. void Dialog::onReadyRead(void)
    66. {
    67. #if defined(USE_QIODEVICE)
    68.  
    69. qDebug() << "received";
    70. ba = sock->readAll();
    71. #else
    72. char data[64];
    73. quint16 port;
    74.  
    75. while(sock->hasPendingDatagrams())
    76. {
    77. sock->readDatagram(data, sizeof(data), &host, &port);
    78. qDebug() << "received";
    79. }
    80.  
    81. #endif
    82. // data processing...
    83. }
    To copy to clipboard, switch view to plain text mode 

    Unfortunately this code doesn't works because when the replies come back from the hosts the interface is (probably already) unbound, and onReadyRead() is never called.

    When I remove definition of USE_QIODEVICE the QUDPSocket methods are used instead of QIODevice.
    In this way all seems to work.

    How can I get the wanted behaviour using only QIODevice methods (apart from connetcing and binding)?

    Best regards
    Max

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: udp broadcasting on all network interfaces

    Why do you want to have such complicated code as connecting and disconnceting when you made it work with the much simpler UDP specific API?

    Cheers,
    _

  3. #3
    Join Date
    May 2009
    Posts
    75
    Thanks
    5
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: udp broadcasting on all network interfaces

    I have to use QIODevice API, I cannot use UDP socket api directly

    Maybe be above sample code is too simplified (for sake of simplicity). A more fitting example could be:
    Qt Code:
    1. class Frame; // frames declaration. It represent data to be sent/receive
    2.  
    3. class FrameManagement: public QObject
    4. {
    5. Q_OBJECT
    6. public:
    7. FrameManagement(QIODevice *p, QObject *parent = 0);
    8. ~FrameManagement();
    9.  
    10. void sendFrame(const Frame &);
    11.  
    12. private:
    13. QIODevice *m_iodevice;
    14.  
    15. private slots:
    16. void processPendingData(void);
    17.  
    18. signals:
    19. void frameReceived(Frame);
    20. };
    21.  
    22. FrameManagement::FrameManagement(QIODevice *p, QObject *parent) :
    23. m_iodevice(p),
    24. QObject(parent)
    25. {
    26. if(NULL != m_iodevice)
    27. connect(m_iodevice, &QIODevice::readyRead, this, &FrameManagement::processPendingData);
    28.  
    29. }
    30.  
    31. FrameManagement::sendFrame(const Frame &frame)
    32. {
    33.  
    34. ba = frame.toByteArray(); // a frame can be converted in a QByteArray
    35.  
    36. /*
    37.   * here I use QIODevice::write(), and cannot use UDP api, because is supposed I don't know that m_iodevice is a QUdpSocket
    38.   * It could be QTcpSocket, or QSerialPort
    39.   */
    40. m_iodevice->write(ba);
    41. }
    42.  
    43.  
    44. void FrameManagement::processPendingData(void)
    45. {
    46.  
    47. qDebug() << "received";
    48. /*
    49.   * here I use QIODevice::readAll(), and cannot use UDP api, because is supposed I don't know that m_iodevice is a QUdpSocket
    50.   * It could be QTcpSocket, or QSerialPort
    51.   */
    52. ba = sock->readAll();
    53.  
    54. Frame frame;
    55.  
    56. frame.fromByteArray(ba); // A ByteArray can be validated and converted in Frame
    57.  
    58. if(frame.isValid())
    59. emit frameReceived(frame);
    60. }
    61.  
    62.  
    63. class Dialog : public QDialog
    64. {
    65. Q_OBJECT
    66.  
    67. public:
    68. explicit Dialog(QWidget *parent = 0);
    69. ~Dialog();
    70.  
    71. private:
    72. Ui::Dialog *ui;
    73. QUdpSocket *sock;
    74. FrameManagement *framemanagement;
    75.  
    76.  
    77. public slots:
    78. void onFrameArrived(Frame);
    79. void onButtonClicked(void);
    80. };
    81.  
    82.  
    83. Dialog::Dialog(QWidget *parent) :
    84. QDialog(parent),
    85. ui(new Ui::Dialog)
    86. {
    87. ui->setupUi(this);
    88.  
    89. connect(ui->pushBtn,SIGNAL(clicked()), this, SLOT(onButtonClicked()));
    90.  
    91. qDebug() << qVersion();
    92.  
    93. sock = new QUdpSocket(this);
    94. connect(sock, &QUdpSocket::readyRead, this, &Dialog::onReadyRead);
    95.  
    96. framemanagement = new FrameManagement(sock, this);
    97. connect(framemanagement,SIGNAL(frameReceived(Frame)), this, SLOT(onFrameArrived(Frame)));
    98. }
    99.  
    100. void Dialog::onButtonClicked(void)
    101. {
    102. Frame frame;
    103. // initiaalize frame
    104.  
    105. QList<QNetworkInterface> list = QNetworkInterface::allInterfaces();
    106. foreach (QNetworkInterface iface, list)
    107. {
    108. QList<QNetworkAddressEntry> AEList = iface.addressEntries();
    109. foreach(QNetworkAddressEntry AE, AEList)
    110. {
    111. if(AE.broadcast().protocol() == QAbstractSocket::IPv4Protocol)
    112. {
    113. sock->bind(54366); // I have to call bind() for every interface because disconnectFromHost() unbind
    114. sock->connectToHost(AE.broadcast(), 44444); // I have to call connectToHost to make the subsequent call to write() works
    115. qDebug() << sock->localPort();
    116. framemanagement->sendFrame(frame);
    117. sock->disconnectFromHost(); // I have to call disconnectFromHost() otherwise the subsequent call to connectToHost() will fail
    118. qDebug() << "send to" << AE.broadcast();
    119. }
    120. }
    121. }
    122. }
    123.  
    124. void Dialog::onFrameArrived(Frame frame)
    125. {
    126. // suppose I have overloaded operator<< for Frame
    127. qDebug() << "frame arrived" << frame;
    128.  
    129. // frame elaboration
    130. // ...
    131. }
    To copy to clipboard, switch view to plain text mode 

    As you can see che code does not direct call the read() and write() api. It do throug FrameManagement class, that doesn't know which kind of device is (QUdpSocket, QTcpSocket, QSerialPort or some others...)
    Infacts all datails about the actual nature of Device (QUdpSocket) is in the Dialog class, that setup the QIODevice in the right way so that FrameManagement can safetly call readAll() and write() methods.

    I wonder if I need one UDP socket (and a FrameManagement) for every network interface, in this way every socket can be bound and connected only once, and I can connect FrameManagement::frameReceived() of every object to onFrameArrived().
    This should works, but I wonder if there is a more smart manner to do using only one socket as in the previous example where, commenting out
    Qt Code:
    1. #define USE_QIODEVICE
    To copy to clipboard, switch view to plain text mode 
    the method QUdpSocket::writeDatagram() is used

    best regards
    max

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: udp broadcasting on all network interfaces

    Hmm, I see.

    Maybe you are abstracting too early then.
    If you had an abstract frame management that would then be implemented depending on the connection type, then the respective specialization could make use of whatever underlying API it has available.

    In any case the constant conncet/disconnect looks terrible, have you considered having one device per "connection".

    If you really need to use a single device, make sure you actually wait for it to complete each task, e.g. wait for it to be connected, wait for it to have sent the data, wait for it to disconnect.
    Obviously you will never be able to recieve any response, since you never keep any port bound. but maybe that's ok for your use case.

    Cheers,
    _

  5. #5
    Join Date
    May 2009
    Posts
    75
    Thanks
    5
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: udp broadcasting on all network interfaces

    Unfortunately it seems it cannot work.
    When I call QUdpSocket::connectToHost() the connection is established
    To test this I wrote another example:
    test-broadcast.tar.gz

    Qt Code:
    1. #include <QDialog>
    2. #include <QUdpSocket>
    3.  
    4. namespace Ui {
    5. class Dialog;
    6. }
    7.  
    8. class Dialog : public QDialog
    9. {
    10. Q_OBJECT
    11.  
    12. public:
    13. explicit Dialog(QWidget *parent = 0);
    14. ~Dialog();
    15.  
    16. private:
    17. Ui::Dialog *ui;
    18.  
    19. QUdpSocket *sock_uni_udp;
    20. QUdpSocket *sock_uni_qio;
    21. QUdpSocket *sock_broad_udp;
    22. QUdpSocket *sock_broad_qio;
    23.  
    24. public slots:
    25. void recv_uni_udp(void);
    26. void recv_uni_qio(void);
    27. void recv_broad_udp(void);
    28. void recv_broad_qio(void);
    29.  
    30. void btn_uni_udp(void);
    31. void btn_uni_qio(void);
    32. void btn_broad_udp(void);
    33. void btn_broad_qio(void);
    34. };
    35.  
    36.  
    37. #define UNICASTADDR "192.168.155.1"
    38. #define BROADCASTADDR "192.168.155.255"
    39.  
    40. Dialog::Dialog(QWidget *parent) :
    41. QDialog(parent),
    42. ui(new Ui::Dialog)
    43. {
    44. ui->setupUi(this);
    45.  
    46. sock_uni_udp = new QUdpSocket(this);
    47. sock_uni_qio = new QUdpSocket(this);
    48. sock_broad_udp = new QUdpSocket(this);
    49. sock_broad_qio = new QUdpSocket(this);
    50.  
    51. QString str;
    52. QTextStream txtstream(&str);
    53.  
    54. sock_uni_udp->bind();
    55. str.clear();
    56. txtstream << "bound to " << sock_uni_udp->localPort();
    57. ui->uni_udp_port->setText(str);
    58. connect(sock_uni_udp, SIGNAL(readyRead()),this, SLOT(recv_uni_udp()));
    59.  
    60. sock_broad_udp->bind();
    61. str.clear();
    62. txtstream << "bound to " << sock_broad_udp->localPort();
    63. ui->broad_udp_port->setText(str);
    64. connect(sock_broad_udp, SIGNAL(readyRead()),this, SLOT(recv_broad_udp()));
    65.  
    66. sock_broad_qio->bind();
    67. sock_broad_qio->connectToHost(QHostAddress(QString(BROADCASTADDR)),44444);
    68. str.clear();
    69. txtstream << "bound to " << sock_broad_qio->localPort();
    70. ui->broad_qio_port->setText(str);
    71. connect(sock_broad_qio, SIGNAL(readyRead()),this, SLOT(recv_broad_qio()));
    72.  
    73. sock_uni_qio->bind();
    74. sock_uni_qio->connectToHost(QHostAddress(QString(UNICASTADDR)),44444);
    75. str.clear();
    76. txtstream << "bound to " << sock_uni_qio->localPort();
    77. ui->uni_qio_port->setText(str);
    78. connect(sock_uni_qio, SIGNAL(readyRead()),this, SLOT(recv_uni_qio()));
    79.  
    80.  
    81. connect(ui->uni_udp_api_btn, SIGNAL(clicked()),this,SLOT(btn_uni_udp()));
    82. connect(ui->uni_qio_api_btn, SIGNAL(clicked()),this,SLOT(btn_uni_qio()));
    83. connect(ui->broad_udp_api_btn, SIGNAL(clicked()),this,SLOT(btn_broad_udp()));
    84. connect(ui->broad_qio_api_btn, SIGNAL(clicked()),this,SLOT(btn_broad_qio()));
    85. }
    86.  
    87. Dialog::~Dialog()
    88. {
    89. delete sock_uni_udp;
    90. delete sock_uni_qio;
    91. delete sock_broad_udp;
    92. delete sock_broad_qio;
    93.  
    94. delete ui;
    95. }
    96.  
    97. void Dialog::btn_uni_udp(void)
    98. {
    99. sock_uni_udp->writeDatagram("hallo",5, QHostAddress(QString(UNICASTADDR)),44444);
    100. }
    101.  
    102. void Dialog::btn_uni_qio(void)
    103. {
    104. sock_uni_qio->write("hallo");
    105. }
    106.  
    107. void Dialog::btn_broad_udp(void)
    108. {
    109. sock_broad_udp->writeDatagram("hallo",5, QHostAddress(QString(BROADCASTADDR)),44444);
    110. }
    111.  
    112. void Dialog::btn_broad_qio(void)
    113. {
    114. sock_broad_qio->write("hallo");
    115. }
    116.  
    117.  
    118. void Dialog::recv_uni_udp(void)
    119. {
    120. char str[5];
    121. sock_uni_udp->readDatagram(str, 5);
    122. ui->uni_udp_recv->setText("arrived");
    123. }
    124.  
    125. void Dialog::recv_uni_qio(void)
    126. {
    127. ba = sock_uni_udp->readAll();
    128. ui->uni_qio_recv->setText("arrived");
    129.  
    130. }
    131.  
    132. void Dialog::recv_broad_udp(void)
    133. {
    134. char str[5];
    135. sock_broad_udp->readDatagram(str, 5);
    136. ui->broad_udp_recv->setText("arrived");
    137. }
    138.  
    139. void Dialog::recv_broad_qio(void)
    140. {
    141. ba = sock_broad_qio->readAll();
    142. ui->broad_qio_recv->setText("arrived");
    143. }
    To copy to clipboard, switch view to plain text mode 

    In this example I test all four combination: QIODevice API broadcast and unicast, QUdpSochet API broadcast and unicast
    in the contructor all sockets are bound and the window is:


    and netstat output (only the entry involved) is:
    Qt Code:
    1. max@kinets-dev:~$ netstat -nupa
    2. (Not all processes could be identified, non-owned process info
    3. will not be shown, you would have to be root to see it all.)
    4. Active Internet connections (servers and established)
    5. Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
    6. udp 0 0 192.168.155.100:53527 192.168.155.1:44444 ESTABLISHED 4405/test-broadcast
    7. udp 0 0 192.168.155.100:50986 192.168.155.255:44444 ESTABLISHED 4405/test-broadcast
    8. udp6 0 0 :::50762 :::* 4405/test-broadcast
    9. udp6 0 0 :::42704 :::* 4405/test-broadcast
    To copy to clipboard, switch view to plain text mode 
    In the first two lines I used connectToHost() api and the connection state is established. The only one that cannot receive udp datagrams is the second. My thought is that since the connection is established it can receive packet only from 192.168.155.255, but when the peer reply it use its own unicast address so the packet is discarded.
    This is confirmed also by whireshark:


    So the question now is: Is possible and how to send in broadcast but being able to receive replies using QIODevice API?

    best regards
    max
    Attached Images Attached Images

  6. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: udp broadcasting on all network interfaces

    I guess at this point the best way is to check the code.
    Maybe connectToHost() calls bind again or unbinds, etc.

    But you should ask yourself if this is really worth it if you can just simply use the API that you know to work and abstract yourself.

    Cheers,
    _

  7. #7
    Join Date
    May 2009
    Posts
    75
    Thanks
    5
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: udp broadcasting on all network interfaces

    yes

    now I try to use upd api directly

    best regards
    max

  8. #8
    Join Date
    Apr 2016
    Posts
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: udp broadcasting on all network interfaces

    You can use decorator pattern. Decorate QIODevice and use UDP API inside it.

    Regards,
    Aleksei

  9. #9
    Join Date
    Apr 2016
    Posts
    1
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: udp broadcasting on all network interfaces

    This is the code I came up to be run in a console for broadcasting using a single ip:


    Qt Code:
    1. // myudp.h
    2. #ifndef MYUDP_H
    3. #define MYUDP_H
    4.  
    5. #include <QObject>
    6. #include <QUdpSocket>
    7.  
    8. class MyUDP : public QObject
    9. {
    10. Q_OBJECT
    11. public:
    12. explicit MyUDP(QObject *parent = 0);
    13. void HelloUDP();
    14. signals:
    15.  
    16. public slots:
    17. void readyRead();
    18.  
    19. private:
    20. QUdpSocket *socket;
    21.  
    22. };
    23.  
    24. #endif // MYUDP_H
    25. //end of myudp.h
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. // myudp.cpp
    2. #include "myudp.h"
    3.  
    4. #define BROADCAST_IP "192.168.2.210"
    5.  
    6. MyUDP::MyUDP(QObject *parent) :
    7. QObject(parent)
    8. {
    9. // create a QUDP socket
    10. socket = new QUdpSocket(this);
    11.  
    12.  
    13. // The most common way to use QUdpSocket class is
    14. // to bind to an address and port using bind()
    15. // bool QAbstractSocket::bind(const QHostAddress & address,
    16. // quint16 port = 0, BindMode mode = DefaultForPlatform)
    17.  
    18. //socket->bind(QHostAddress::LocalHost, 1234);
    19. socket->bind(QHostAddress(QString(BROADCAST_IP)),1234);
    20.  
    21. connect(socket, SIGNAL(readyRead()),this, SLOT(readyRead()));
    22. }
    23.  
    24. void MyUDP::HelloUDP()
    25. {
    26. QByteArray Data;
    27. Data.append("This message has been broadcasted ;)");
    28.  
    29. // Sends the datagram datagram
    30. // to the host address and at port.
    31.  
    32. //socket->writeDatagram(Data, QHostAddress::LocalHost, 1234);
    33. socket->writeDatagram(Data, QHostAddress(QString(BROADCAST_IP)),1234);
    34. }
    35.  
    36. void MyUDP::readyRead()
    37. {
    38. // when data comes in
    39. QByteArray buffer;
    40. buffer.resize(socket->pendingDatagramSize());
    41.  
    42. QHostAddress sender;
    43. quint16 senderPort;
    44.  
    45. // qint64 QUdpSocket::readDatagram(char * data, qint64 maxSize,
    46. // QHostAddress * address = 0, quint16 * port = 0)
    47. // Receives a datagram no larger than maxSize bytes and stores it in data.
    48. // The sender's host address and port is stored in *address and *port
    49. // (unless the pointers are 0).
    50.  
    51. socket->readDatagram(buffer.data(), buffer.size(),
    52. &sender, &senderPort);
    53.  
    54. qDebug() << "Message from: " << sender.toString();
    55. qDebug() << "Message port: " << senderPort;
    56. qDebug() << "Message: " << buffer;
    57. }
    58. // end of myudp.cpp
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. // main.cpp
    2. #include <QCoreApplication>
    3. #include "myudp.h"
    4.  
    5. int main(int argc, char *argv[])
    6. {
    7. QCoreApplication a(argc, argv);
    8.  
    9. MyUDP client;
    10.  
    11. client.HelloUDP();
    12.  
    13. return a.exec();
    14. }
    15. // end of main.cpp
    To copy to clipboard, switch view to plain text mode 
    Attached Files Attached Files
    Last edited by anda_skoa; 11th April 2016 at 15:42. Reason: missing [code] tags

Similar Threads

  1. broadcasting signals through the application
    By tuli in forum Qt Programming
    Replies: 3
    Last Post: 1st March 2015, 00:05
  2. How to get list of physical network interfaces?
    By hitmaneidos in forum Qt Programming
    Replies: 2
    Last Post: 2nd February 2012, 03:17
  3. Broadcasting a signal ?
    By squidge in forum Qt Programming
    Replies: 8
    Last Post: 17th November 2009, 00:07
  4. Qt Designer for web interfaces
    By rbp in forum Qt Tools
    Replies: 3
    Last Post: 14th October 2009, 03:01
  5. QUdpSocket - Multiple Network Interfaces
    By dbrmik in forum Qt Programming
    Replies: 0
    Last Post: 24th April 2009, 14:47

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.