本系列所有文章可以在這里查看[http://blog.csdn.net/cloud_castle/article/category/2123873](http://blog.csdn.net/cloud_castle/article/category/2123873)
上次在該系列第一篇博文里提到QTcp的同步構建方式,這個例子涉及線程等,知識點比較多。我們還是由淺入深,今天再看個簡單的例子吧~
按例看下Broadcast Sender Example的介紹吧,這對第一時間了解這個例程是有好處的~
Demonstrates how to broadcast information to multiple clients on a local network.
This example uses Qt Network APIs to demonstrate how to broadcast messages to multiple clients over a local network.
main主函數沒有特別的東西,來看sender.h:
~~~
#ifndef SENDER_H
#define SENDER_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QDialogButtonBox;
class QLabel;
class QPushButton;
class QTimer;
class QUdpSocket;
QT_END_NAMESPACE
class Sender : public QWidget
{
Q_OBJECT
public:
Sender(QWidget *parent = 0);
private slots:
void startBroadcasting();
void broadcastDatagram();
private:
QLabel *statusLabel;
QPushButton *startButton;
QPushButton *quitButton;
QDialogButtonBox *buttonBox;
QUdpSocket *udpSocket;
QTimer *timer;
int messageNo;
};
#endif
~~~
可以發現這個頭文件像Multicast Sender的頭文件一樣簡單,甚至比它更簡單。因為它連QHostAddress成員都沒有。
sender.cpp:
~~~
#include <QtWidgets>
#include <QtNetwork>
#include "sender.h"
Sender::Sender(QWidget *parent)
: QWidget(parent)
{
statusLabel = new QLabel(tr("Ready to broadcast datagrams on port 45454"));
statusLabel->setWordWrap(true); // 這個屬性的設置使得statusLabel的文字可以在合適的位置換行
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);
//! [0]
udpSocket = new QUdpSocket(this);
//! [0]
messageNo = 1;
connect(startButton, SIGNAL(clicked()), this, SLOT(startBroadcasting()));
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
connect(timer, SIGNAL(timeout()), this, SLOT(broadcastDatagram()));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(statusLabel);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
setWindowTitle(tr("Broadcast Sender"));
}
void Sender::startBroadcasting()
{
startButton->setEnabled(false);
timer->start(1000);
}
void Sender::broadcastDatagram()
{
statusLabel->setText(tr("Now broadcasting datagram %1").arg(messageNo));
//! [1]
QByteArray datagram = "Broadcast message " + QByteArray::number(messageNo);
udpSocket->writeDatagram(datagram.data(), datagram.size(), // 第(1)點
QHostAddress::Broadcast, 45454);
//! [1]
++messageNo;
}
~~~
第一點,發送數據的語句就這一條,與Multicast唯一的區別在于使用了一個QHostAddress的枚舉變量Broadcast,它相當于QHostAddress(“255,255,255,255”)。
好了,來看Broadcast Receiver的實現。receiver.h:
~~~
#ifndef RECEIVER_H
#define RECEIVER_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QLabel;
class QPushButton;
class QUdpSocket;
class QAction;
QT_END_NAMESPACE
class Receiver : public QWidget
{
Q_OBJECT
public:
Receiver(QWidget *parent = 0);
private slots:
void processPendingDatagrams();
private:
QLabel *statusLabel;
QPushButton *quitButton;
QUdpSocket *udpSocket;
};
#endif
~~~
receiver.cpp:
~~~
#include <QtWidgets> // 第(1)點
#include <QtNetwork>
#include "receiver.h"
Receiver::Receiver(QWidget *parent)
: QWidget(parent)
{
statusLabel = new QLabel(tr("Listening for broadcasted messages"));
statusLabel->setWordWrap(true);
quitButton = new QPushButton(tr("&Quit"));
//! [0]
udpSocket = new QUdpSocket(this);
udpSocket->bind(45454, QUdpSocket::ShareAddress); // 綁定端口,共享地址模式
//! [0]
//! [1]
connect(udpSocket, SIGNAL(readyRead()),
this, SLOT(processPendingDatagrams()));
//! [1]
connect(quitButton, SIGNAL(clicked()), this, SLOT(close()));
QHBoxLayout *buttonLayout = new QHBoxLayout; // 以控件為Layout命名,而不是Layout1,Layout2...
buttonLayout->addStretch(1);
buttonLayout->addWidget(quitButton);
buttonLayout->addStretch(1);
QVBoxLayout *mainLayout = new QVBoxLayout; // 最外層的布局mainLayout
mainLayout->addWidget(statusLabel);
mainLayout->addLayout(buttonLayout);
setLayout(mainLayout);
setWindowTitle(tr("Broadcast Receiver"));
}
void Receiver::processPendingDatagrams() // 接收端的處理函數與Multicast一模一樣
{
//! [2]
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size());
statusLabel->setText(tr("Received datagram: \"%1\"")
.arg(datagram.data()));
}
//! [2]
}
~~~
第一點,個人不推薦這種頭文件的包含方式,官方Demo為了簡明這樣做了,但這樣會使包含的文件過多,最好用到什么包含什么,雖然會多寫幾個#include,但是預編譯結束后文件體積會小很多。而且#include優于#include,這樣頭文件的層次更清晰。
好了,其實這個例子與上一個Multicast Sender/Receiver 基本沒有多大區別,但是我們讀例程并不只是關注它核心功能的實現,更多的在于細節的處理。細節決定成敗嘛~
- 前言
- 1——Fortune Server/Client
- 2——Multicast Sender/Receiverz
- 3——Broadcast Sender/Receiver
- 4——Blocking Fortune Client
- 5——Threaded Fortune Server
- 5(總結)——Fortune例程的各個實現區別
- 6——Loopback Example
- 7——Analog Clock Example
- 8——Shaped Clock Example
- 9——Analog Clock Window Example
- 10——Qt Quick Particles Examples - Emitters
- 11——Qt Quick Particles Examples - Affectors
- 12——Qt Quick Particles Examples - CustomParticles
- 13——Qt Quick Particles Examples - Image Particles
- 14——Qt Quick Particles Examples - System
- 15——Chapter 1: Creating a New Type
- 16——Chapter 2: Connecting to C++ Methods and Signals
- 17——Chapter 3: Adding Property Bindings
- 18——Chapter 4: Using Custom Property Types
- 19——Chapter 5: Using List Property Types
- 20——Chapter 6: Writing an Extension Plugin
- 21——Extending QML - Adding Types Example
- 22——Extending QML - Object and List Property Types Example
- 23——Extending QML - Inheritance and Coercion Example
- 24——Extending QML - Default Property Example
- 25——Extending QML - Methods Example
- 26——Extending QML - Grouped Properties Example
- 27——Extending QML - Attached Properties Example
- 28——Extending QML - Signal Support Example
- 29——Extending QML - Property Value Source Example
- 30——Extending QML - Binding Example
- 31——StocQt
- 32——Qt Quick Examples - Threading
- 33——Qt Quick Examples - Window and Screen
- 34——Concentric Circles Example
- 35——Music Player
- 36——Wiggly Example
- 37——Vector Deformation