Qt5官方Demo解析集2——Multicast Sender/Receiverz

来源:互联网 发布:金融大数据网站有哪些 编辑:程序博客网 时间:2024/05/24 06:39

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873


在上篇博文中记录了Fortune Server/Client Example,那个例子基于Tcp传输协议的,Tcp是一种可靠协议,但是有时候我们并不在意数据包是否被成功投递,这种情况尤其出现在一些不断重复数据的发送上,比如每秒一次的温度,时间等。在这种情况下我们往往倾向使用Udp来发送和接收UDP数据报(datagram)。今天Multicast Sender/Receiver这个例子就是一个基于QUdpSocket实现的UDP组播发送。并且使用TTL(Time To Live)来控制网络开销。


按照惯例,看看官方介绍吧:

Demonstrates how to send messages to a multicast group
This example demonstrates how to send messages to the clients of a multicast group.



好了,那我们进主题,先看multicastsender文件包里面的sender.h:

#ifndef SENDER_H#define SENDER_H#include <QDialog>#include <QHostAddress>QT_BEGIN_NAMESPACEclass QDialogButtonBox;class QLabel;class QPushButton;class QTimer;class QUdpSocket;class QSpinBox;QT_END_NAMESPACEclass Sender : public QDialog{    Q_OBJECTpublic:    Sender(QWidget *parent = 0);private slots:    void ttlChanged(int newTtl);    void startSending();    void sendDatagram();private:    QLabel *statusLabel;    QLabel *ttlLabel;    QSpinBox *ttlSpinBox;    QPushButton *startButton;    QPushButton *quitButton;    QDialogButtonBox *buttonBox;    QUdpSocket *udpSocket;    QTimer *timer;    QHostAddress groupAddress;    int messageNo;};#endif
如果有上一篇博文的基础,这里就没什么好说的了。。。注意这个messageNo在源文件是作为计数使用,不是Nomessage,而是No.message。。。好的取名对理解程序是有很大帮助的。


sender.cpp:

#include <QtWidgets>#include <QtNetwork>#include "sender.h"Sender::Sender(QWidget *parent)    : QDialog(parent){    groupAddress = QHostAddress("239.255.43.21"); //IANA网络,可以作为局域网IP    statusLabel = new QLabel(tr("Ready to multicast datagrams to group %1 on port 45454").arg(groupAddress.toString()));    ttlLabel = new QLabel(tr("TTL for multicast datagrams:"));  // 控件布局    ttlSpinBox = new QSpinBox;    ttlSpinBox->setRange(0, 255);    QHBoxLayout *ttlLayout = new QHBoxLayout;    ttlLayout->addWidget(ttlLabel);    ttlLayout->addWidget(ttlSpinBox);    startButton = new QPushButton(tr("&Start"));    quitButton = new QPushButton(tr("&Quit"));    buttonBox = new QDialogButtonBox;    buttonBox->addButton(startButton, QDialogButtonBox::ActionRole);    buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);    timer = new QTimer(this);      udpSocket = new QUdpSocket(this); // udpSocket在这里初始化    messageNo = 1;    connect(ttlSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ttlChanged(int)));    connect(startButton, SIGNAL(clicked()), this, SLOT(startSending()));    connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));    connect(timer, SIGNAL(timeout()), this, SLOT(sendDatagram())); // 重复性的数据发送,可以看到使用Udp的场合    QVBoxLayout *mainLayout = new QVBoxLayout;    mainLayout->addWidget(statusLabel);    mainLayout->addLayout(ttlLayout);    mainLayout->addWidget(buttonBox);    setLayout(mainLayout);    setWindowTitle(tr("Multicast Sender"));    ttlSpinBox->setValue(1);}void Sender::ttlChanged(int newTtl){    udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, newTtl); // 这里是将网络设置成Multicast_TTL模式,第二个参数是TTL最大路由数}void Sender::startSending(){    startButton->setEnabled(false);    timer->start(1000);}void Sender::sendDatagram(){    statusLabel->setText(tr("Now sending datagram %1").arg(messageNo));    QByteArray datagram = "Multicast message " + QByteArray::number(messageNo); // 这里没有使用QDataStrem,因为数据无须校验。    udpSocket->writeDatagram(datagram.data(), datagram.size(), // 调用writeDatagram函数,这里使用writeDatagram(datagram, groupAddress, 45454)也是可以的                             groupAddress, 45454);    ++messageNo;}
Sender端代码就是这样了,是不是觉得官方demo也不难理解~

ok,继续来看receiver.h和receiver.cpp:

receiver.h:

#ifndef RECEIVER_H#define RECEIVER_H#include <QDialog>#include <QHostAddress>QT_BEGIN_NAMESPACEclass QLabel;class QPushButton;class QUdpSocket;QT_END_NAMESPACEclass Receiver : public QDialog{    Q_OBJECTpublic:    Receiver(QWidget *parent = 0);private slots:    void processPendingDatagrams();private:    QLabel *statusLabel;    QPushButton *quitButton;    QUdpSocket *udpSocket;    QHostAddress groupAddress;};

不用说什么了吧。

receiver.cpp:
#include <QtWidgets>#include <QtNetwork>#include "receiver.h"Receiver::Receiver(QWidget *parent)    : QDialog(parent){    groupAddress = QHostAddress("239.255.43.21"); // 与发送端取同样的IP地址    statusLabel = new QLabel(tr("Listening for multicasted messages"));    quitButton = new QPushButton(tr("&Quit"));    udpSocket = new QUdpSocket(this);    udpSocket->bind(QHostAddress::AnyIPv4, 45454, QUdpSocket::ShareAddress); // 绑定了任意的IPv4地址,45454端口,并允许其他服务使用该端口    udpSocket->joinMulticastGroup(groupAddress); // 以操作系统默认接口加入Multicast网络组    connect(udpSocket, SIGNAL(readyRead()), // 数据流过来触发readyRead()信号            this, SLOT(processPendingDatagrams()));    connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));    QHBoxLayout *buttonLayout = new QHBoxLayout; // 按钮居中    buttonLayout->addStretch(1);    buttonLayout->addWidget(quitButton);    buttonLayout->addStretch(1);    QVBoxLayout *mainLayout = new QVBoxLayout;    mainLayout->addWidget(statusLabel);    mainLayout->addLayout(buttonLayout);    setLayout(mainLayout);    setWindowTitle(tr("Multicast Receiver"));}void Receiver::processPendingDatagrams(){    while (udpSocket->hasPendingDatagrams()) { // 是否有待处理的信号        QByteArray datagram;        datagram.resize(udpSocket->pendingDatagramSize()); // 以数据包的大小初始化datagram        udpSocket->readDatagram(datagram.data(), datagram.size()); // 直接读就可以了        statusLabel->setText(tr("Received datagram: \"%1\"")                              .arg(datagram.data()));    }}
Ok,今天的学习先到这里吧~



2 0
原创粉丝点击