Examples: Update multicast sender and receiver examples for IPv6

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 <marten.nordheim@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
Thiago Macieira 2017-12-12 13:55:32 -08:00
parent c5a3022b04
commit f9c07da7b6
4 changed files with 52 additions and 18 deletions

View File

@ -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;
@ -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()));
}
}

View File

@ -71,8 +71,10 @@ private slots:
private:
QLabel *statusLabel = nullptr;
QUdpSocket udpSocket;
QHostAddress groupAddress;
QUdpSocket udpSocket4;
QUdpSocket udpSocket6;
QHostAddress groupAddress4;
QHostAddress groupAddress6;
};
#endif

View File

@ -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);
@ -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()
@ -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;
}

View File

@ -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;
};