Skip to content

Commit

Permalink
Examples: Update multicast sender and receiver examples for IPv6
Browse files Browse the repository at this point in the history
It's the right thing to do, as we're in 2017, not 1997. Also, this takes
care to indicate that QAbstractSocket::MulticastTtlOption makes sense
mostly for IPv4, even though it's implemented for both families. In
IPv4, it's used to indicatae the scope, whereas in IPv6 it's stored in
bits 12-15 of the address.

Task-number: QTBUG-46046
Change-Id: I9741f017961b410c910dfffd14ffaabe0a2024d8
Reviewed-by: Mårten Nordheim <[email protected]>
Reviewed-by: Timur Pocheptsov <[email protected]>
  • Loading branch information
thiagomacieira committed Dec 24, 2017
1 parent c5a3022 commit f9c07da
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 18 deletions.
35 changes: 26 additions & 9 deletions examples/network/multicastreceiver/receiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@

Receiver::Receiver(QWidget *parent)
: QDialog(parent),
groupAddress(QStringLiteral("239.255.43.21"))
groupAddress4(QStringLiteral("239.255.43.21")),
groupAddress6(QStringLiteral("ff12::2115"))
{
statusLabel = new QLabel(tr("Listening for multicasted messages"));
statusLabel = new QLabel(tr("Listening for multicast messages on both IPv4 and IPv6"));
auto quitButton = new QPushButton(tr("&Quit"));

auto buttonLayout = new QHBoxLayout;
Expand All @@ -72,21 +73,37 @@ Receiver::Receiver(QWidget *parent)

setWindowTitle(tr("Multicast Receiver"));

udpSocket.bind(QHostAddress::AnyIPv4, 45454, QUdpSocket::ShareAddress);
udpSocket.joinMulticastGroup(groupAddress);
udpSocket4.bind(QHostAddress::AnyIPv4, 45454, QUdpSocket::ShareAddress);
udpSocket4.joinMulticastGroup(groupAddress4);

connect(&udpSocket, SIGNAL(readyRead()),
if (!udpSocket6.bind(QHostAddress::AnyIPv6, 45454, QUdpSocket::ShareAddress) ||
!udpSocket6.joinMulticastGroup(groupAddress6))
statusLabel->setText(tr("Listening for multicast messages on IPv4 only"));

connect(&udpSocket4, SIGNAL(readyRead()),
this, SLOT(processPendingDatagrams()));
connect(&udpSocket6, &QUdpSocket::readyRead, this, &Receiver::processPendingDatagrams);
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
}

void Receiver::processPendingDatagrams()
{
QByteArray datagram;
while (udpSocket.hasPendingDatagrams()) {
datagram.resize(int(udpSocket.pendingDatagramSize()));
udpSocket.readDatagram(datagram.data(), datagram.size());
statusLabel->setText(tr("Received datagram: \"%1\"")

// using QUdpSocket::readDatagram (API since Qt 4)
while (udpSocket4.hasPendingDatagrams()) {
datagram.resize(int(udpSocket4.pendingDatagramSize()));
udpSocket4.readDatagram(datagram.data(), datagram.size());
statusLabel->setText(tr("Received IPv4 datagram: \"%1\"")
.arg(datagram.constData()));
}

// using QUdpSocket::receiveDatagram (API since Qt 5.8)
while (udpSocket6.hasPendingDatagrams()) {
QNetworkDatagram dgram = udpSocket6.receiveDatagram();
statusLabel->setText(statusLabel->text() +
tr("\nReceived IPv6 datagram from [%2]:%3: \"%1\"")
.arg(dgram.data().constData(), dgram.senderAddress().toString())
.arg(dgram.senderPort()));
}
}
6 changes: 4 additions & 2 deletions examples/network/multicastreceiver/receiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ private slots:

private:
QLabel *statusLabel = nullptr;
QUdpSocket udpSocket;
QHostAddress groupAddress;
QUdpSocket udpSocket4;
QUdpSocket udpSocket6;
QHostAddress groupAddress4;
QHostAddress groupAddress6;
};

#endif
23 changes: 18 additions & 5 deletions examples/network/multicastsender/sender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,21 @@

Sender::Sender(QWidget *parent)
: QDialog(parent),
groupAddress(QStringLiteral("239.255.43.21"))
groupAddress4(QStringLiteral("239.255.43.21")),
groupAddress6(QStringLiteral("ff12::2115"))
{
statusLabel = new QLabel(tr("Ready to multicast datagrams to group %1 on port 45454").arg(groupAddress.toString()));
// force binding to their respective families
udpSocket4.bind(QHostAddress(QHostAddress::AnyIPv4), 0);
udpSocket6.bind(QHostAddress(QHostAddress::AnyIPv6), udpSocket4.localPort());

auto ttlLabel = new QLabel(tr("TTL for multicast datagrams:"));
QString msg = tr("Ready to multicast datagrams to groups %1 and [%2] on port 45454").arg(groupAddress4.toString());
if (udpSocket6.state() != QAbstractSocket::BoundState)
msg = tr("IPv6 failed. Ready to multicast datagrams to group %1 on port 45454").arg(groupAddress4.toString());
else
msg = msg.arg(groupAddress6.toString());
statusLabel = new QLabel(msg);

auto ttlLabel = new QLabel(tr("TTL for IPv4 multicast datagrams:"));
auto ttlSpinBox = new QSpinBox;
ttlSpinBox->setRange(0, 255);

Expand Down Expand Up @@ -88,7 +98,8 @@ Sender::Sender(QWidget *parent)

void Sender::ttlChanged(int newTtl)
{
udpSocket.setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl);
// we only set the TTL on the IPv4 socket, as that changes the multicast scope
udpSocket4.setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl);
}

void Sender::startSending()
Expand All @@ -101,6 +112,8 @@ void Sender::sendDatagram()
{
statusLabel->setText(tr("Now sending datagram %1").arg(messageNo));
QByteArray datagram = "Multicast message " + QByteArray::number(messageNo);
udpSocket.writeDatagram(datagram, groupAddress, 45454);
udpSocket4.writeDatagram(datagram, groupAddress4, 45454);
if (udpSocket6.state() == QAbstractSocket::BoundState)
udpSocket6.writeDatagram(datagram, groupAddress6, 45454);
++messageNo;
}
6 changes: 4 additions & 2 deletions examples/network/multicastsender/sender.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,11 @@ private slots:
private:
QLabel *statusLabel = nullptr;
QPushButton *startButton = nullptr;
QUdpSocket udpSocket;
QUdpSocket udpSocket4;
QUdpSocket udpSocket6;
QTimer timer;
QHostAddress groupAddress;
QHostAddress groupAddress4;
QHostAddress groupAddress6;
int messageNo = 1;
};

Expand Down

0 comments on commit f9c07da

Please sign in to comment.