Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QUdpSocket seems to stop receiving data from multicast group

QUdpSocket seems to stop receiving data from multicast group

Scheduled Pinned Locked Moved General and Desktop
8 Posts 4 Posters 3.8k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • marinasM Offline
    marinasM Offline
    marinas
    wrote on last edited by kshegunov
    #1

    I have a networked application where all the participants continously publish their status on a multicast address. Any participant then knows the status of all the other participants. But at some point a participant stops receiving anything on the QUdpSocket, but the others still receive status messages from that participant. It can take anyting from 15 minutes to 3 hours before this happens. I have made a sample console application that also has this problem. Compile and start at least two instances and wait for one of them to stop receiving anything. For convinience the application takes a name argument to separate connections from each others.
    I´m running on Red Hat Enterprise 7.1 (64 bit) and I´m using Qt 5.5.0 an GCC 4.8.3.
    Can anyone see a problem with this code?

    Connection.h -------------

    #ifndef UDPCONNECTION_H
    #define UDPCONNECTION_H
    
    #include <QObject>
    #include <QUdpSocket>
    #include <QByteArray>
    #include <QTimer>
    
    class UdpConnection : public QObject
    {
      Q_OBJECT
      public:
      explicit UdpConnection( QString name, QObject* parent = 0);
      virtual ~UdpConnection();
    
      void join();
      void leave();
    
      public slots:
      void sendDatagram();
      void readPendingDatagrams();
    
      private:
      Q_DISABLE_COPY( UdpConnection )
    
      QString m_name;
      QHostAddress m_multicastAddress;
      int m_port;
      QUdpSocket m_socket;
    
      QByteArray m_content;
      QTimer m_sendTimer;
    };
    
    #endif
    

    Connection.cpp ---------------------------

    #include "connection.h"
    #include <QDataStream>
    #include <QDateTime>
    #include <QDebug>
    
    UdpConnection::UdpConnection( QString name, QObject* parent )
      : QObject( parent ),
        m_name( name ),
        m_multicastAddress( "224.4.4.10" ),
        m_port( 13589 ),
        m_socket( this),
        m_content(),
        m_send_timer( this )
    {
      QString content = m_name;
      content.append( " - This is just some meaningless stuff to pass as data" );
    
      QDataStream out( &m_content, QIODevice::WriteOnly );
      out.setVersion( QDataStream::Qt_5_4 );
      out << content;
    
      QObject::connect( &m_timer, &Qtimer::timeout, this, &UdpConnection::sendDatagram );
      m_sendTimer.setInterval( 100 );
    }
    
    UdpConnection::~UdpConnection()
    {
      leave();
    }
    
    void UdpConnection::join()
    {
      if( !m_socket.bind( m_multicastAddress, (qint16)m_port,
          QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint ) )
      {
        qDebug() << "Socket error reported: " << m_socket.errorString();
        qDebug() << "Failed to bind to port, will not join.";
        return;
      }
    
      QObject::connect( &m_socket, &QUdpSocket::readyRead, this, &UdpConnection::readPendingDatagrams );
    
      if( !m_socket.joinMulticastGroup( m_multicastAddress ) )
      {
        qDebug() << "Failed to join, closing socket" ;
        m_socket.close();
        return;
      }
    
      //setting ttl to zero to avoid traffic on network
      m_socket.setSocketOption( QAbstractSocket::MulticastTtlOption, QVariant(0) );
    
      qDebug() << "Socket " << m_name << " has joined. " << QdateTime::currentDateTimeUtc().toString( Qt::ISODate );
      m_sendTimer.start()
    }
    
    void UdpConnection::leave()
    {
      m_sendTimer.stop();
    
      if( !m_socket.leaveMulticastGroup( m_multicastAddress ) )
      {
        qDebug() << "Failed to leave group, disconnecting ready read signal.";
        QObject::disconnect( &m_socket, &QUdpSocket::readyRead, this, &UdpConnection::readPendingDatagrams );
        return;
      }
    
      QObject::disconnect( &m_socket, &QUdpSocket::readyRead, this, &UdpConnection::readPendingDatagrams );
      m_socket.close();
      qDebug() << "Socket " << m_name << " closed.";
    }
    
    void UdpConnection::sendDatagram()
    {
      m_socket.writeDatagram( m_content, m_multicastAddress, (qint16)m_port );
    }
    
    void UdpConnection::readPendingDatagrams()
    {
      while( m_socket.hasPendingDatagrams() )
      {
        QByteArray datagram;
        datagram.resize( (int)m_socket.pendingDatagramSize() );
        m_socket.readDatagram( datagram.data(), datagram.size() );
    
        QDataStream in( &datagram, QIODevice::ReadOnly );
        in.setVersion( QDataStream::Qt_5_4 );
        QString content;
        in >> content;
    
        //print and discard content
        qDebug() << m_name << " received " << content << " " << QDateTime::currentDateTimeUtc().toString( Qt::ISODate );
      }
    }
    

    main.cpp ------------------------

    #include <QCoreApplication>
    #include "connection.h"
    
    int main( int argc, char *argv[] )
    {
      QCoreApplication a(argc, argv );
      QString connectionName;
    
      if( qApp->arguments().count() <= 1 )
        connectionName = "A";
      else
        connectionName = qApp->arguments().at( 1 );
    
      UdpConnection connection( connectionName );
      connection.join();
    {
    m_sendTimer.stop();
    
    if( !m_socket.leaveMulticastGroup( m_multicastAddress ) )
    {
    qDebug() << "Failed to leave group, disconnecting ready read signal.";
    QObject::disconnect( &m_socket, &QUdpSocket::readyRead, this, &UdpConnection::readPendingDatagrams );
    return;
    }
    
    QObject::disconnect( &m_socket, &QUdpSocket::readyRead, this, &UdpConnection::readPendingDatagrams );
    m_socket.close();
    qDebug() << "Socket " << m_name << " closed.";
    }
    
    void UdpConnection::sendDatagram()
    {
    m_socket.writeDatagram( m_content, m_multicastAddress, (qint16)m_port );
    }
    
    void UdpConnection::readPendingDatagrams()
    {
    while( m_socket.hasPendingDatagrams() )
    {
    QByteArray datagram;
    datagram.resize( (int)m_socket.pendingDatagramSize() );
    m_socket.readDatagram( datagram.data(), datagram.size() );
    
    QDataStream in( &datagram, QIODevice::ReadOnly );
    in.setVersion( QDataStream::Qt_5_4 );
    QString content;
    in >> content;
    
    //print and discard content
    qDebug() << m_name << " received " << content << " " << QDateTime::currentDateTimeUtc().toString( Qt::ISODate );
    
      return a.exec();
    }
    

    UdpConnection.pro ------------------------

    QT += core network
    QT -= gui
    
    CONFIG += c++11
    
    TARGET = UdpConnection
    CONFIG += console
    CONFIG -= app_bundle
    
    TEMPLATE = app
    
    SOURCES += main.cpp \
    connection.cpp
    
    HEADERS += \
    connection.h
    

    [Added code tags ~kshegunov]

    1 Reply Last reply
    0
    • m.sueM Offline
      m.sueM Offline
      m.sue
      wrote on last edited by
      #2

      Hi,
      It could be a timing problem or some overflow. With the latter I mean that the program processing the data may be slower than the program providing the data and at some point in time its buffer is full.
      It would be interesting to know what the program is doing when it stops processing the Udp data. Have you attached an debugger to it in this situation and called "break" in the menu? Does the problem perhaps not appear in release version as e.g. the qDebug call takes its time?
      -Michael.

      marinasM 1 Reply Last reply
      1
      • m.sueM m.sue

        Hi,
        It could be a timing problem or some overflow. With the latter I mean that the program processing the data may be slower than the program providing the data and at some point in time its buffer is full.
        It would be interesting to know what the program is doing when it stops processing the Udp data. Have you attached an debugger to it in this situation and called "break" in the menu? Does the problem perhaps not appear in release version as e.g. the qDebug call takes its time?
        -Michael.

        marinasM Offline
        marinasM Offline
        marinas
        wrote on last edited by
        #3

        Hi,
        It´s an interressting theory, but the test program, that just prints and discards data until there is no more data to read, has the same behaviour/error. See readPendingDatagrams() method. Also compiled and ran test program on RHEL 7.3 machine ( different HW and different network ) and it still has the same issue. In both cases I also checked with netstat -g to make sure the router did not drop a connection from the multicast group.
        -marinas-

        kshegunovK 1 Reply Last reply
        0
        • marinasM marinas

          Hi,
          It´s an interressting theory, but the test program, that just prints and discards data until there is no more data to read, has the same behaviour/error. See readPendingDatagrams() method. Also compiled and ran test program on RHEL 7.3 machine ( different HW and different network ) and it still has the same issue. In both cases I also checked with netstat -g to make sure the router did not drop a connection from the multicast group.
          -marinas-

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #4

          Have you tried actually debugging as @m.sue suggested. After the problem manifests itself you can interrupt the program and add a breakpoint to see if any datagrams are received. I can't see anything wrong with it at a glance, but that's a doesn't mean there isn't a problem hidden somewhere.

          Read and abide by the Qt Code of Conduct

          marinasM 1 Reply Last reply
          0
          • kshegunovK kshegunov

            Have you tried actually debugging as @m.sue suggested. After the problem manifests itself you can interrupt the program and add a breakpoint to see if any datagrams are received. I can't see anything wrong with it at a glance, but that's a doesn't mean there isn't a problem hidden somewhere.

            marinasM Offline
            marinasM Offline
            marinas
            wrote on last edited by
            #5

            @kshegunov
            I have tried debugging it and the only thing happening is that the sendDatagram() method is still called every 100 ms as the timer times out. The other instance of the application still receives data from the instance that does not receive anything, not even the echo of its own data.

            kshegunovK 1 Reply Last reply
            0
            • marinasM marinas

              @kshegunov
              I have tried debugging it and the only thing happening is that the sendDatagram() method is still called every 100 ms as the timer times out. The other instance of the application still receives data from the instance that does not receive anything, not even the echo of its own data.

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by
              #6

              @marinas said in QUdpSocket seems to stop receiving data from multicast group:

              I have tried debugging it and the only thing happening is that the sendDatagram() method is still called every 100 ms as the timer times out.

              But you don't get any incoming data through the readyRead() signal? That's rather strange. Perhaps you could try wireshark or another packet sniffer to see if packages are getting to the machine in question?

              Read and abide by the Qt Code of Conduct

              C 1 Reply Last reply
              0
              • kshegunovK kshegunov

                @marinas said in QUdpSocket seems to stop receiving data from multicast group:

                I have tried debugging it and the only thing happening is that the sendDatagram() method is still called every 100 ms as the timer times out.

                But you don't get any incoming data through the readyRead() signal? That's rather strange. Perhaps you could try wireshark or another packet sniffer to see if packages are getting to the machine in question?

                C Offline
                C Offline
                ChristianJ
                wrote on last edited by
                #7

                @kshegunov Could you finally solve your problem? Because it seems that I am experiencing the same difficulty...
                If you solved it how did you modify your UDP datagram receiver code?

                kshegunovK 1 Reply Last reply
                0
                • C ChristianJ

                  @kshegunov Could you finally solve your problem? Because it seems that I am experiencing the same difficulty...
                  If you solved it how did you modify your UDP datagram receiver code?

                  kshegunovK Offline
                  kshegunovK Offline
                  kshegunov
                  Moderators
                  wrote on last edited by
                  #8

                  The original poster didn't follow up, and haven't posted a solution, sorry.

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved