Qt TCP/UDP 网络协议入门实操(二)UDP通讯


在这里插入图片描述


GitHub 源码:     QWidgetLearningPro 选择 NetTools

QT Widge 其它文章请点击这里:     QT Widget 学习笔记


姊妹篇:     

Qt TCP/UDP 网络协议入门实操(一)TCP通讯

Qt TCP/UDP 网络协议入门实操(二)UDP通讯

Qt TCP/UDP 网络协议入门实操(补充)

此文只是最简单的入门学习,需进一步可以看 飞扬青云 大佬的源码 QWidgetDemo, 选择 nettool ,已经是非常完善的网络调试助手了


UDP(User Datagram Protocol即用户数据报协议)是一个轻量级的,不可靠的,面向数据报的无连接协议。我们现在几乎每个人都使用的QQ,其聊天时就是使用UDP协议进行消息发送的。就像QQ那样,当有很多用户,发送的大部分都是短消息,要求能及时响应,并且对安全性要求不是很高的情况下使用UDP协议。在选择使用协议的时候,选择UDP必须要谨慎。在网络质量令人十分不满意的环境下,UDP协议数据包丢失会比较严重。但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。所以qq这种对保密要求并不太高的聊天程序就是使用的UDP协议。

在Qt中提供了QUdpSocket 类来进行UDP数据报(datagrams)的发送和接收。这里我们还要了解一个名词Socket,也就是常说的“套接字”。Socket简单地说,就是一个IP地址加一个port端口 。因为我们要传输数据,就要知道往哪个机子上传送,而IP地址确定了一台主机,但是这台机子上可能运行着各种各样的网络程序,我们要往哪个程序中发送呢?这时就要使用一个端口来指定UDP程序。所以说,Socket指明了数据报传输的路径。

此段摘自:浅谈 Qt 中 UDP 之 UdpSocket通信实例

一、UDP 客户端

在Qt 中使用UDP 客户端通讯演示如下:
在这里插入图片描述
● 实操流程图
在这里插入图片描述

● 代码

udpclinet.cpp

#include "udpclinet.h"
#include "ui_udpclinet.h"

UdpClinet::UdpClinet(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::UdpClinet)
{
    ui->setupUi(this);
    initForm();
}

UdpClinet::~UdpClinet()
{
    delete ui;
}

//1. UI
//2. 初始化
//① 创建 QTcpSocket 套接字对象
//② 建立socket 接收缓冲数据的信号槽(readyRead)
void UdpClinet::initForm()
{
    socket = new QUdpSocket(this);
    connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
}

//3. 接收UDP数据
void UdpClinet::readData()
{
    QHostAddress host;
    quint16 port;
    QByteArray data;

    while (socket->hasPendingDatagrams()) {
        data.resize(socket->pendingDatagramSize());
        socket->readDatagram(data.data(), data.size(), &host, &port);
        QString str = QString("[%1:%2] %3").arg(host.toString()).arg(port).arg(QString(data));

        ui->txtMain->setTextColor(QColor("red"));
        ui->txtMain->append(str);
    }
}

//4. 发送UDP数据 (socket->connectToHost)
//  在连接按键中,获取手动输入的服务器IP地址和端口号
void UdpClinet::on_btnSend_clicked()
{
    UdpServerIP = ui->txtServerIP->text().trimmed();
    UdpServerPort = ui->txtServerPort->text().trimmed().toInt();

    QString data = ui->cboxData->currentText();
    if (data.length() <= 0) {
        return;
    }

    QByteArray buffer = data.toUtf8();

    socket->writeDatagram(buffer, QHostAddress(UdpServerIP), UdpServerPort);

    QString str = QString("[发送:%1:%2] %3").arg(UdpServerIP).arg(UdpServerPort).arg(data);

    ui->txtMain->setTextColor(QColor("darkgreen"));
    ui->txtMain->append(str);
}


udpclinet.h

#ifndef UDPCLINET_H
#define UDPCLINET_H

#include <QWidget>
#include <QtNetwork>

namespace Ui {
class UdpClinet;
}

class UdpClinet : public QWidget
{
    Q_OBJECT

public:
    explicit UdpClinet(QWidget *parent = nullptr);
    void initForm();
    ~UdpClinet();

private:
    Ui::UdpClinet *ui;
    QUdpSocket *socket;

    QString UdpServerIP;         
    int UdpServerPort;

private slots:
    void readData();

private slots:
    void on_btnSend_clicked();
};

#endif // UDPCLINET_H

二、UDP 服务器

在Qt 中使用UDP 服务器通讯演示如下:
在这里插入图片描述

● 实操流程图

在这里插入图片描述
● 代码

udpserver.cpp

#include "udpserver.h"
#include "ui_udpserver.h"

UdpServer::UdpServer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::UdpServer)
{
    ui->setupUi(this);
    initForm();
}

UdpServer::~UdpServer()
{
    delete ui;
}

//1. ui
//2. 初始化
//① 创建 QUdpSocket 套接字对象
//② 建立socket 接收缓冲数据的信号槽(readyRead)
void UdpServer::initForm()
{
    socket = new QUdpSocket(this);
    connect(socket, SIGNAL(readyRead()), this, SLOT(readData()));
}

//3.开启监听, IP不指定,端口自定义
void UdpServer::on_btnListen_clicked()
{
    UdpServerPort = ui->txtListenPort->text().trimmed().toInt();
    if (ui->btnListen->text() == "监听") {
        if (socket->bind(QHostAddress::AnyIPv4, UdpServerPort)) {
            ui->btnListen->setText("关闭");
        }
    } else {
        socket->abort();
        ui->btnListen->setText("监听");
    }
}

//4. 接收UDP客户端数据,获取UDP客户端IP和端口号,并保存到 listWidget 中
void UdpServer::readData()
{
    QHostAddress host;
    quint16 port;
    QByteArray data;

    while (socket->hasPendingDatagrams()) {
        data.resize(socket->pendingDatagramSize());
        socket->readDatagram(data.data(), data.size(), &host, &port);

        //ip
        QString ip = host.toString();
        ip = ip.replace("::ffff:", "");
        if (ip.isEmpty()) {
            continue;
        }

        QString str = QString("[%1:%2] %3").arg(ip).arg(port).arg(QString(data));
        ui->txtMain->setTextColor(QColor("red"));
        ui->txtMain->append(str);

        //添加到 listWidget 列表中
        QString listData = QString("%1:%2").arg(ip).arg(port);
        for (int i = 0; i < ui->listWidget->count(); i++) {
            QString s = ui->listWidget->item(i)->text();
            if (listData == s) {
                return;
            }
        }
        ui->listWidget->addItem(listData);
        ui->labCount->setText(QString("%1个客户端").arg(ui->listWidget->count()));
    }
}

//5. 发送数据到UDP客户端
//   利用已保存的客户端IP和端口号发送
void UdpServer::on_btnSend_clicked()
{
    QString data = ui->cboxData->currentText();
    if (data.length() <= 0) {
        return;
    }

    int row = ui->listWidget->currentRow();
    if (row >= 0) {
        QString str = ui->listWidget->item(row)->text();
        QStringList list = str.split(":");
        QString ip = list.at(0);
        quint16 port = list.at(1).toInt();

        socket->writeDatagram(data.toUtf8(), QHostAddress(ip), port);

        QString strPrint = QString("[%1:%2] %3").arg(ip).arg(port).arg(data);
        ui->txtMain->setTextColor(QColor("darkgreen"));
        ui->txtMain->append(strPrint);
    }
}


udpserver.h

#ifndef UDPSERVER_H
#define UDPSERVER_H

#include <QWidget>
#include <QtNetwork>

namespace Ui {
class UdpServer;
}

class UdpServer : public QWidget
{
    Q_OBJECT

public:
    explicit UdpServer(QWidget *parent = nullptr);
    ~UdpServer();
    void initForm();

private:
    Ui::UdpServer *ui;
    QUdpSocket *socket;
    int UdpServerPort;

private slots:
    void readData();

private slots:
    void on_btnListen_clicked();
    void on_btnSend_clicked();
};

#endif // UDPSERVER_H

源码:     NetToolsTest

QT Widge 其它文章请点击这里:     QT Widget 学习笔记


姊妹篇:     

Qt TCP/UDP 网络协议入门实操(一)TCP通讯

Qt TCP/UDP 网络协议入门实操(二)UDP通讯

Qt TCP/UDP 网络协议入门实操(补充)


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值