Qt 网络编程-UDP

11 篇文章 12 订阅


简述:

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

适用于以下几种情况:


A . 网络数据大多为短消息

B . 拥有大量客户端

C . 对数据安全性无特殊要求

D . 网络负担非常重,但对响应速度要求高


同样,如果要在Qt 进行网络编程首先需要在 .pro文件添加: QT += network。Qt 中通过 QUdpSocket类实现UDP 协议的编程。

本文介绍一个基于 UDP 协议广播应用 ,它由UDP 服务器 UDP 客户端两部分组成。

其实,UDP没有特定的server端 和 client,简单来说就是向特定的ip发送报文,所以,也可以分为发送端接收端

QUdpSocket类允许发送和接收 UDP 数据报,继承自QAbstractSocket 。QUdpSocket 支持IPv4 广播。QUdpSocket 还支持多播


操作系统:windows 7

Qt构建套件:qt-opensource-windows-x86-mingw530-5.7.0.exe

Qt Creator版本:4.0.2



1、 UDP 协议工作原理及编程模型


1 > UDP 协议工作原理


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





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


2  > UDP 编程模型


基于UDP 协议经典编程模型,程序编写的通用流程如下:





由上图可知,在 UDP 方式下,客户端与服务器建立连接,它只负责调用发送函数向服务器发出数据报。同样,服务器也不与客户端接收连接,只负责调用接收函数,等待来自某客户端的数据到达。


2、 UDP 接收端


Qt 的 UdpSocket 接收消息原则:

A . new一个UdpSocket

B . 调用UdpSocketbind方法,同时指定端口号

C . 使用 connect 将接收消息函数和UdpSocket对象做关联

D . 在接受消息槽函数当中调用 readDatagram 接收消息


udpclient.h

#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.cpp

#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); //创建一个UdpSocket
    //连接QIODevice的readyRead()信号,readyRead()表示有消息到来这个信号,
    connect(udpSocket,SIGNAL(readyRead()),this,SLOT(dataReceived()));
    //指定绑定端口号,接收消息必须绑定端口号,发送消息则不需要绑定
    bool result=udpSocket->bind(port);//绑定到指定的端口上
    //取消绑定端口号使用:udpsocket->close()方法
    if(!result)
    {
        QMessageBox::information(this,tr("error"),tr("udp socket create error!"));
        return;
    }
}

UdpClient::~UdpClient()
{
    
}

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

void UdpClient::dataReceived()
{
    //判断UdpSocket中是否有数据可读
    while(udpSocket->hasPendingDatagrams())
    {
        //实现读取数据报
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(),datagram.size());

        QString msg=datagram.data();
        ReceiveTextEdit->insertPlainText(msg);
    }
}


3、UDP 发送端


Qt 的 UdpSocket 发送消息:

A . new 一个 UdpSocket

B . 调用 writeDatagram 发送消息



udpserver.h

#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.cpp

#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); //创建一个UdpSocket
    //定时发送广播信息
    timer = new QTimer(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(timeout()));
}

UdpServer::~UdpServer()
{
    
}

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;
    }
    //QHostAddress::Broadcast 指定向广播地址发送,可以改成固定IP,则表示向特定IP发送
    if((length=udpSocket->writeDatagram(msg.toLatin1(),msg.length(),QHostAddress::Broadcast,port))!=msg.length())
    {
        return;
    }
}


4、运行








  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值