基于UDP(User Data Protocol,用户数据报协议)的网络广播程序
1、 UDP是一种简单轻量级、不可靠、面向数据报、无连接的传输层协议,可以应用在可靠性不是十分重要的场合,如短消息、广播信息等。
2、 特点
网络数据大多为短消息
拥有大量的客户端
对数据安全性无特殊要求
网络负担非常重要,但对响应速度要求高
3、 UDP客户端与服务器间的交互时序
4、 服务器端编程
udpserver.cpp文件
#ifndef UDPSERVER_H
#define UDPSERVER_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QUdpSocket>
#include <QTimer>
class UdpServer : public QDialog
{
Q_OBJECT
public:
UdpServer(QWidget *parent = 0,Qt::WindowFlags f=0);
~UdpServer();
public slots:
void StartBtnClicked();
void timeout();
private:
QLabel *TimerLabel;
QLineEdit *TextLineEdit;
QPushButton *StartBtn;
QVBoxLayout *mainLayout;
int port;
bool isStarted;
QUdpSocket *udpSocket;
QTimer *timer;
};
#endif // UDPSERVER_H
Udpserver.h文件
#include "udpserver.h"
#include <QHostAddress>
UdpServer::UdpServer(QWidget *parent,Qt::WindowFlags f)
: QDialog(parent,f)
{
setWindowTitle(tr("UDP Server")); //设置窗体的标题
/* 初始化各个控件 */
TimerLabel = new QLabel(tr("计时器:"),this);
TextLineEdit = new QLineEdit(this);
StartBtn = new QPushButton(tr("开始"),this);
/* 设置布局 */
mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(TimerLabel);
mainLayout->addWidget(TextLineEdit);
mainLayout->addWidget(StartBtn);
connect(StartBtn,SIGNAL(clicked()),this,SLOT(StartBtnClicked()));
port = 5555; //设置UDP的端口号参数,服务器定时向此端口发送广播信息
isStarted = false;
udpSocket = new QUdpSocket(this);//创建一个QUdpSocket
timer = new QTimer(this); //定时发送广播信息
connect(timer,SIGNAL(timeout()),this,SLOT(timeout()));
}
void UdpServer::StartBtnClicked()
{
if(!isStarted)//判断语句,如果为真的话
{
StartBtn->setText(tr("停止"));
timer->start(1000);//以1000毫秒为周期启动计时器(1秒=1000毫秒)
isStarted =true;
}
else
{
StartBtn->setText(tr("开始"));
isStarted = false;
timer->stop();
}
}
void UdpServer::timeout()
{
QString msg = TextLineEdit->text();//把TextLineEdit的内容赋给msg
int length=0;
if(msg=="")//判断,如果msg为空的话
{
return;
}
if((length=udpSocket->writeDatagram(msg.toLatin1(),
msg.length(),QHostAddress::Broadcast,port))!=msg.length())//QHostAddress::Broadcast ?
{
return;
}
}
UdpServer::~UdpServer()
{
}
知识点1:if(!)
if( !a )就是一个判断语句,判断表达式 !a 的真假,进而决定是否执行后续操作。如果a是一个变量,当a等于0时,!a=1(为真),执行后续操作;当a不等于0时,!a=0(为假),不执行后续操作;如果a是一个表达式,将表达式的值计算出来,当成变量来操作,判断过程同上。
知识点2:writeDatagram(msg.toLatin1(),msg.length(),QHostAddress::Broadcast,port)
qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port) 以大小为size的数据报发送到端口port的主机地址address。 返回成功发送的字节数; 否则返回-1。
知识点3:信号与槽
1代表要发射信号的类2.代表该类触发的某一个信号,3代表要触发槽的类,4代表要触发类的槽函数
5、 客户端编程
Udpclient.cpp文件
#ifndef UDPCLIENT_H
#define UDPCLIENT_H
#include <QDialog>
#include <QVBoxLayout>
#include <QTextEdit>
#include <QPushButton>
#include <QUdpSocket>
class UdpClient : public QDialog
{
Q_OBJECT
public:
UdpClient(QWidget *parent = 0,Qt::WindowFlags f=0);
~UdpClient();
public slots:
void CloseBtnClicked();
void dataReceived();
private:
QTextEdit *ReceiveTextEdit;
QPushButton *CloseBtn;
QVBoxLayout *mainLayout;
int port;
QUdpSocket *udpSocket;
};
#endif // UDPCLIENT_H
udpclient.h文件
#include "udpclient.h"
#include <QMessageBox>
#include <QHostAddress>
UdpClient::UdpClient(QWidget *parent,Qt::WindowFlags f)
: QDialog(parent,f)
{
setWindowTitle(tr("UDP Client")); //设置窗体的标题
/* 初始化各个控件 */
ReceiveTextEdit = new QTextEdit(this);
CloseBtn = new QPushButton(tr("Close"),this);
/* 设置布局 */
mainLayout=new QVBoxLayout(this);
mainLayout->addWidget(ReceiveTextEdit);
mainLayout->addWidget(CloseBtn);
connect(CloseBtn,SIGNAL(clicked()),this,SLOT(CloseBtnClicked()));
port =5555; //设置UDP的端口号参数,指定在此端口上监听数据
udpSocket = new QUdpSocket(this); //创建一个QUdpSocket
connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));
//连接QIODevice的readyRead()信号,QUdpSocket是I/O设备,当数据到达时,发出readyRead()信号
bool result=udpSocket->bind(port); //绑定到指定的端口上
if(!result)//判断为假时
{
QMessageBox::information(this,tr("error"),tr("udp socket create error!"));//打开带有给定标题error和文本的信息udp socket create error!消息框。
return;
}
}
void UdpClient::CloseBtnClicked()
{
close();
}
void UdpClient::dataReceived()
{
while(udpSocket->hasPendingDatagrams())//判断UdpSocket中是否有数据报可读,hasPendingDatagrams()在至少有一个数据报可读时返回true,否则返回false
{
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(),datagram.size());
//读取数据报
QString msg=datagram.data();
ReceiveTextEdit->insertPlainText(msg); //insertPlainText()插入纯文本,显示数据内容
}
}
UdpClient::~UdpClient()
{
}