Qt 网络编程-UDP

来源:互联网 发布:网校用什么软件 编辑:程序博客网 时间:2024/05/17 09:26


简述:

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、运行








原创粉丝点击