Qt5开发从入门到精通——第十篇二节(Qt5 网络与通信—— 基于 UDP 的网络广播程序)

欢迎小伙伴的点评✨✨,相互学习c/c++应用开发。
博主 本着开源的精神交流Qt开发的经验、将持续更新续章,为社区贡献博主自身的开源精神‍

目录

  • 前言
  • 一、基于 TCP 的网络聊天室程序概述
    • 1.1、UDP工作原理
    • 1.2、UDP 编程模型
  • 二、效果实例
  • 三、原码解析
    • 3.1首先先在新建好的工程文件xxx.pro文件中加入
    • udpclient.h
    • udpserver.h
    • main.cpp
    • udpclient.cpp
    • udpserver.cpp
  • 四、总结

前言

本章节会给大家带来Qt5 网络与通信—— 基于 UDP 的网络广播程序实例详解。

一、基于 TCP 的网络聊天室程序概述

用户数据报协议 (User Data Protocol, UDP) 是一种简单轻量级、不可靠、面向数据报、无连接的传输层协议,可以应用在可靠性不是十分重要的场合,如短消息、广播信息等。

适合应用的情况有以下几种:

  • 网络数据大多为短消息。
  • 拥有大量客户端。
  • 对数据安全性无特殊要求。
  • 网络负担非常重,但对响应速度要求高。

1.1、UDP工作原理

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

请求
应答
UDP客户端
UDP服务器

例如,常用的聊天工具一腾讯 QQ 软件就是使用 UDP 发送消息的,因此有时会出现收不
到消息的情况。

1.2、UDP 编程模型

下面介绍基于UDP 的经典编程模型, UDP 客户端与服务器间的交互时序如下图所示 。
可以看出,在 UDP 方式下,客户端并不与服务器建立连接,它只负责调用发送函数向服务器发出数据报。类似地,服务器也不从客户端接收连接,只负责调用接收函数,等待来自某客户端的数据到达。
Qt 中通过 QUdpSocket 类实现 UDP 协议的编程。下面通过一个实例,介绍如何实现基于
UDP 的广播应用,它由 UDP 服务器和 UDP 客户端两部分组成。
Qt5开发从入门到精通——第十篇二节(Qt5 网络与通信—— 基于 UDP 的网络广播程序)_第1张图片

二、效果实例

图一
Qt5开发从入门到精通——第十篇二节(Qt5 网络与通信—— 基于 UDP 的网络广播程序)_第2张图片

三、原码解析

3.1首先先在新建好的工程文件xxx.pro文件中加入

QT       += network

udpclient.h

#ifndef UDPCLIENT_H
#define UDPCLIENT_H

#include 
#include 
#include 
#include 
#include 
class UdpClient : public QDialog
{
    Q_OBJECT
public:
    UdpClient(QWidget *parent= 0,Qt::WindowFlags f=0);
    ~UdpClient () ;

private:
    QTextEdit *ReceiveTextEdit;
    QPushButton *CloseBtn;
    QVBoxLayout *mainLayout;
public slots:
    void CloseBtnClicked();
    void dataReceived();
private:
    int port;
    QUdpSocket *udpSocket;

};

#endif // UDPCLIENT_H

udpserver.h

#ifndef UDPSERVER_H
#define UDPSERVER_H

#include 
#include 
#include 
#include 
#include 

#include 
#include 
class UdpServer : public QDialog
{
    Q_OBJECT

public:
    explicit UdpServer(QWidget *parent = 0,Qt::WindowFlags f=0);
    ~UdpServer();

private:

QLabel *TimerLabel;
QLineEdit *TextLineEdit;
QPushButton *StartBtn;
QVBoxLayout *mainLayout;
public slots:
    void StartBtnClicked();
    void timeout();
private:
    int port;
    bool isStarted;
    QUdpSocket *udpSocket;
    QTimer *timer;
};

#endif // UDPSERVER_H

main.cpp

#include "udpserver.h"
#include "udpclient.h"
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    UdpServer wS;
    UdpClient wC;
    wS.show();
    wC.show();

    return a.exec();
}

udpclient.cpp

#include "udpclient.h"
#include 
#include 
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 设备,从 QIODevice 继承而来,当有数据到达 I/O
设备时,发出 readyRead()信号。*/
    bool result=udpSocket->bind(port); //绑定到指定的端口上
    if (!result)
    {
        QMessageBox::information(this,tr("error"),tr("udp socket create error!")) ;
        return;
    }
}
void UdpClient::CloseBtnClicked()
{
    close();
}


/*dataReceived() 函数响应 QUdpSocket 的 readyRead()信号,一旦 UdpSocket 对象中有数据可
读时,即通过 readDatagram()方法将数据读出并显示。*/
void UdpClient::dataReceived ()
{
    while (udpSocket->hasPendingDatagrams()) //(a)
    {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize()); /*判断 UdpSocket 中是否有数据报可读,
hasPendingDatagramsO方法在至少有一个数据报可读时返回 true, 否则返回 false 。*/
        udpSocket->readDatagram(datagram.data(),datagram.size());
        QString msg=datagram.data();                /*实现了读取第一个数据报, pendingDatagramSize()可以获得第一个数据报的长度。
同时运行 UdpServer 与 UdpClient 工程,首先在服务器界面的文本框中输入 "hello !", 然后
单击“开始”按钮,按钮文本变为“停止",客户端就开始不断地收到 "hello!" 字符消息并显
示在文本区,当单击服务器的“停止”按钮后,按钮文本又变回“开始”,客户端也就停止了字
符的显示,再次单击服务器的“开始”按钮,客户端又继续接收并显示……如此循环往复*/
        ReceiveTextEdit->insertPlainText(msg);     //显示数据
    }
}

UdpClient::~UdpClient()
{

}

udpserver.cpp

#include "udpserver.h"
#include 
#include 
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);
    timer= new QTimer(this); //创建一个 QUdpSocket
    //定时发送广播信息
    connect (timer, SIGNAL (timeout()), this, SLOT(timeout()));  //每隔1秒调用一次
}

UdpServer::~UdpServer()
{

}

/*使用延时每隔1秒触发一次timeout*/
void UdpServer::StartBtnClicked()
{
    if(!isStarted)
    {
        StartBtn->setText(tr(" 停止")) ;
        timer->start(1000); //每隔1秒发送一次
        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;
    }

}

四、总结

Qt5 网络与通信—— 基于 UDP 的网络广播程序会在应用程序开发中经常用到的。

你可能感兴趣的:(Qt5开发从入门到精通,udp,网络,qt,c++,windows)