Qt with Cascades UI Examples Documentation

Contents

Multicast Receiver Example

Files:

Description

The Multicast Receiver example shows how to receive information that is sent to a multicast group.

Overview

In this example we'll learn how to use the QUdpSocket class to send and receive multicast messages on the network.

The example application is splitted in two executables, multicastsender and multicastreceiver. While the multicastsender allows the user to start the multicasting of messages on the local network, the multicastreceiver will listen on the local network for these messages and display the received ones in the UI.

Receiver

The central class in multicastreceiver is Receiver, which encapsulates the retrieval of the multicasted messages and provides a property to display the content of the received datagrams in the UI.

                // A standard Label
                Label {
                    horizontalAlignment: HorizontalAlignment.Center

                    text: _receiver.status

                    // Defines a text style with custom font size
                    textStyle {
                        color: Color.White
                        base: SystemDefaults.TextStyles.BodyText
                        textAlign: TextAlign.Center
                    }
                }

The 'status' property of the exported Receiver object is bound against the 'text' property of a Label control, so that whenever a new datagram arrives, the text is updated automatically on screen.

    Receiver::Receiver(QObject *parent)
        : QObject(parent)
    {
        // Initialize the multicast address
        m_groupAddress = QHostAddress("239.255.43.21");

        /**
         * Initialize the 'status' property with some data, it will
         * be shown in the UI until the first datagram arrives.
         */
        m_status = tr("Listening for multicasted messages");

        // Create a new UDP socket and bind it against port 45454
        m_udpSocket = new QUdpSocket(this);
        m_udpSocket->bind(45454, QUdpSocket::ShareAddress);

        // Tell the UDP socket which multicast group it should join
        m_udpSocket->joinMulticastGroup(m_groupAddress);

        /**
         * Create signal/slot connection to invoke processPendingDatagrams() whenever
         * a new multicast datagram is received by the socket.
         */
        connect(m_udpSocket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()));
    }

Inside the constructor of the Receiver class, we initialize the 'status' property and create the QUdpSocket object that encapsulates the low-level network communication. By calling bind() we let the socket listen on port 45454 for incoming messages. We also have to tell the socket which multicast group we want to join, that's done by calling joinMulticastGroup(). In the next step we connect the readyRead() signal of the socket, which is emitted whenever a new datagram arrived, against our own slot processPendingDatagrams().

    void Receiver::processPendingDatagrams()
    {
        // Now read all available datagrams from the socket
        while (m_udpSocket->hasPendingDatagrams()) {
            // Create a temporary buffer ...
            QByteArray datagram;

            // ... 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());

            // Update the 'status' property with the content of the received datagram
            m_status = tr("%1").arg(datagram.data());
            emit statusChanged();
        }
    }

In processPendingDatagrams() we check whether the socket still has pending datagrams and if that's the case, we read the next datagram from the socket and store its content in the 'status' property. By emitting the 'statusChanged()' signal, we trigger the reevaluation of all property bindings in the UI where 'status' is used.