QT学习:基于UDP的网络广播程序

用户数据报协议(User Data Protocol,UDP)是一种简单轻量级、不可靠、面向数据报、无连接的 传输层协议,可以应用在可靠性不是十分重要的场合,如短消息、广播信息等。 适合应用的情况有以下几种:
(1)网络数据大多为短消息。
(2) 拥有大量客户端。
(3) 对数据安全性无特殊要求。
(4)网络负担非常重,但对响应速度要求高。

一、UDP工作原理

如下图所示,UDP客户端向UDP服务器发送一定长度的请求报文,报文大小的限制与各系统 的协议实现有关,但不得超过其下层IP规定的64KB;UDP服务器同样以报文形式做出响应。如果服务器未收到此请求,客户端不会进行重发,因此报文的传输是不可靠的。
在这里插入图片描述

二、UDP 编程模型

下面介绍基于UDP的经典编程模型,UDP客户端与服务器间的交互时序如下图所示。 可以看出,在UDP方式下,客户端并不与服务器建立连接,它只负责调用发送函数向服务器发 出数据报。类似地,服务器也不从客户端接收连接,只负责调用接收函数,等待来自某客户端的数据到达。
在这里插入图片描述

三、UDP服务器编程实例

服务器端的编程具体代码如下:
(1)在头文件“udpserver.h”中声明了需要的各种控件,其具体代码如下:

#include <QDialog> 
#include <QLabel> 
#include <QLineEdit> 
#include <QPushButton> 
#include <QVBoxLayout> 
class UdpServer : public QDialog 
{ 
Q_OBJECT 
public: 
UdpServer(QWidget *parent=0,Qt::WindowFlags f=0); 
~UdpServer(); 
private: 
QLabel *TimerLabel; 
QLineEdit *TextLineEdit; 
QPushButton *StartBtn; 
QVBoxLayout *mainLayout; 
};

(2)源文件“udpserver.cpp”的具体代码如下:

#include "udpserver.h" 
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); 
}

(3)服务器界面如下图所示:

在这里插入图片描述
具体操作步骤如下。
(1)在“UdpServer.pro”中添加如下语句:

QT += network 

(2)在头文件“udpserver.h”中添加需要的槽函数,其具体代码如下:

#include <QUdpSocket> 
#include <QTimer> 
public slots: 
void StartBtnClicked(); 
void timeout(); 
private: 
int port; 
bool isStarted; 
QUdpSocket *udpSocket; 
QTimer *timer; 

(3)在源文件“udpserver.cpp”中添加声明:

#include <QHostAddress> 

其中,在构造函数中添加如下代码:

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

StartBtnClicked()函数的具体代码如下:

void UdpServer::StartBtnClicked() 
{ 
if(!isStarted) 
{ 
StartBtn->setText(tr("停止")); 
timer->start(1000); 
isStarted =true; 
}
else 
{ 
StartBtn->setText(tr("开始")); 
isStarted = false; 
timer->stop(); 
} 
} 

timeout()函数完成了向端口发送广播信息的功能,其具体代码如下:

void UdpServer::timeout() 
{ 
QString msg = TextLineEdit->text(); 
int length=0; 
if(msg=="") 
{ 
return; 
}
if((length=udpSocket->writeDatagram(msg.toLatin1(), 
msg.length(),QHostAddress::Broadcast,port))!=msg.length()) 
{ 
return; 
} 
}

四、UDP客户端编程实例

客户端的编程具体代码如下:
(1)在头文件“udpclient.h”中声明了需要的各种控件,其具体代码如下:

#include <QDialog> 
#include <QVBoxLayout> 
#include <QTextEdit> 
#include <QPushButton> 
class UdpClient : public QDialog 
{ 
Q_OBJECT 
public: 
UdpClient(QWidget *parent = 0,Qt::WindowFlags f=0); 
~UdpClient(); 
private: 
QTextEdit *ReceiveTextEdit; 
QPushButton *CloseBtn; 
QVBoxLayout *mainLayout; 
}; 

(2)源文件“udpclient.cpp”的具体代码如下:

#include "udpclient.h" 
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); 
} 

(3)客户端界面如下图所示:
在这里插入图片描述
以上只是完成了客户端界面的实现,下面完成它的数据接收和显示的功能。
操作步骤如下。
(1)在“UdpClient.pro”中添加如下语句:

QT += network 

(2)在头文件“udpclient.h”中添加如下代码:

#include <QUdpSocket> 
public slots: 
void CloseBtnClicked(); 
void dataReceived(); 
private: 
int port; 
QUdpSocket *udpSocket; 

(3)在源文件“udpclient.cpp”中添加如下声明:

#include <QMessageBox> 
#include <QHostAddress> 

其中,在构造函数中添加的代码如下:

connect(CloseBtn,SIGNAL(clicked()),this,SLOT(CloseBtnClicked())); 
port =5555; //设置UDP的端口号参数,指定在此端口上监听数据 
udpSocket = new QUdpSocket(this); //创建一个QUdpSocket 
connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived())); 
bool result=udpSocket->bind(port); //绑定到指定的端口上 
if(!result) 
{ 
QMessageBox::information(this,tr("error"),tr("udp socket create error!")); 
return; 
} 

CloseBtnClicked()函数的具体内容如下:

void UdpClient::CloseBtnClicked() 
{ 
close(); 
} 

dataReceived()函数响应QUdpSocket的readyRead()信号,一旦UdpSocket对象中有数据可读时,即
通过readDatagram()方法将数据读出并显示。其具体代码如下:

void UdpClient::dataReceived() 
{ 
while(udpSocket->hasPendingDatagrams()) 
{ 
QByteArray datagram; 
datagram.resize(udpSocket->pendingDatagramSize()); 
udpSocket->readDatagram(datagram.data(),datagram.size());  
QString msg=datagram.data(); 
ReceiveTextEdit->insertPlainText(msg); //显示数据内容 
} 
} 

同时运行服务器端与客户端工程,首先在服务器界面的文本框中输入“hello!”,然后单击“开始”按钮,按钮文本变为“停止”,客户端就开始不断地收到“hello!”字符消息并显示在文本区,当单击服务器的“停止”按钮后,按钮文本又变回“开始”,客户端也就停止了字符的显示,再次单击服务器的“开始”按钮,客户端又继续接收并显示,如此循环往复,效果如下图所示。
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值