Qt UDP广播工具开发教程

Qt UDP广播工具开发教程

项目描述

本项目是一个基于Qt5.9.9开发的UDP广播工具,支持UDP广播消息的发送和接收。该工具具有友好的图形界面,可以实现手动发送、自动发送、消息监听等功能,适用于网络通信测试、设备发现、消息广播等场景。

主要特性

  • UDP广播发送: 支持向255.255.255.255发送广播消息
  • UDP广播接收: 支持监听指定端口接收广播消息
  • 多网络接口支持: 自动检测并支持选择不同的网络接口
  • 自动发送功能: 支持定时自动发送消息
  • 消息记录: 完整的发送和接收消息记录
  • 实时状态显示: 状态栏实时显示操作状态

技术栈

  • 开发环境: Windows 10
  • 开发工具: Qt5.9.9
  • 编译器: MinGW32
  • Qt模块 :
    • core: 核心功能
    • gui: 图形界面
    • widgets: 界面控件
    • network: 网络通信

源码下载

完整源代码下载地址:https://download.csdn.net/download/weixin_42059464/91691481

项目结构

复制代码
07_UDPBroadcastingTool/
├── 07_UDPBroadcastingTool.pro    # Qt项目文件
├── main.cpp                       # 程序入口
├── mainwindow.h                   # 主窗口头文件
├── mainwindow.cpp                 # 主窗口实现
├── mainwindow.ui                  # 主窗口界面文件
├── udpsender.h                    # UDP发送器头文件
├── udpsender.cpp                  # UDP发送器实现
├── udpreceiver.h                  # UDP接收器头文件
├── udpreceiver.cpp                # UDP接收器实现
└── README.md                      # 项目说明文档

核心功能实现

1. 界面设计

主界面采用分组布局设计,分为四个主要区域:

xml 复制代码
<!-- 配置参数区域 -->
<widget class="QGroupBox" name="configGroupBox">
    <property name="title">
        <string>配置参数</string>
    </property>
    <!-- 本地IP地址下拉框、发送端口、监听端口、自动发送间隔 -->
</widget>

<!-- 发送控制区域 -->
<widget class="QGroupBox" name="sendGroupBox">
    <property name="title">
        <string>发送控制</string>
    </property>
    <!-- 消息输入框、发送按钮、自动发送控制 -->
</widget>

<!-- 接收控制区域 -->
<widget class="QGroupBox" name="receiveGroupBox">
    <property name="title">
        <string>接收控制</string>
    </property>
    <!-- 开始/停止监听、清空记录 -->
</widget>

<!-- 消息记录区域 -->
<widget class="QGroupBox" name="messageGroupBox">
    <property name="title">
        <string>消息记录</string>
    </property>
    <!-- 消息显示文本框 -->
</widget>

2. 信号槽机制

项目大量使用Qt的信号槽机制实现组件间通信:

cpp 复制代码
// 主窗口构造函数中的信号槽连接
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , udpSender(new UDPSender(this))      // 创建UDP发送器
    , udpReceiver(new UDPReceiver(this))  // 创建UDP接收器
    , autoSendTimer(new QTimer(this))     // 创建自动发送定时器
{
    ui->setupUi(this);
    setupUI();
    updateLocalIP();                      // 检测并显示本地IP地址
  
    // 连接UDP组件的信号和槽
    connect(udpSender, &UDPSender::messageSent, this, &MainWindow::on_messageSent);
    connect(udpReceiver, &UDPReceiver::messageReceived, this, &MainWindow::on_messageReceived);
    connect(autoSendTimer, &QTimer::timeout, this, &MainWindow::autoSendTimerTimeout);
  
    // 连接UI控件的信号和槽
    connect(ui->localIPComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
            this, &MainWindow::on_localIPComboBox_currentIndexChanged);
}

3. 网络接口检测

自动检测系统中所有可用的网络接口和IP地址:

cpp 复制代码
/**
 * 更新本地IP地址列表
 * 核心逻辑:遍历网络接口,获取所有可用的IPv4地址
 */
void MainWindow::updateLocalIP()
{
    ui->localIPComboBox->clear();
  
    QStringList ipList;
    QStringList interfaceNames;
  
    // 遍历所有网络接口
    foreach(const QNetworkInterface &interface, QNetworkInterface::allInterfaces()) {
        // 只处理已启用且非回环的接口
        if (interface.flags().testFlag(QNetworkInterface::IsUp) &&
            !interface.flags().testFlag(QNetworkInterface::IsLoopBack)) {
        
            // 遍历接口的所有IP地址
            foreach(const QNetworkAddressEntry &entry, interface.addressEntries()) {
                QHostAddress address = entry.ip();
                if (address.protocol() == QAbstractSocket::IPv4Protocol) {
                    QString ip = address.toString();
                    QString interfaceName = interface.humanReadableName();
                    QString displayText = QString("%1 (%2)").arg(ip).arg(interfaceName);
                
                    ipList << ip;
                    interfaceNames << interfaceName;
                    ui->localIPComboBox->addItem(displayText, ip);
                }
            }
        }
    }
  
    // 设置默认IP地址
    if (!ipList.isEmpty()) {
        localIP = ipList.first();
        ui->localIPComboBox->setCurrentIndex(0);
    } else {
        localIP = "127.0.0.1";
        ui->localIPComboBox->addItem("未检测到网络连接 (127.0.0.1)", "127.0.0.1");
    }
}

4. UDP广播发送

UDP发送器类实现广播消息发送功能:

cpp 复制代码
/**
 * UDP广播发送器类
 * 核心功能:向255.255.255.255发送UDP广播消息
 */
class UDPSender : public QObject
{
    Q_OBJECT

public:
    explicit UDPSender(QObject *parent = nullptr);
    ~UDPSender();

    bool sendMessage(const QString &message, quint16 port);  // 发送UDP广播消息
    void setBroadcastAddress(const QString &address);        // 设置广播地址

signals:
    void messageSent(const QString &message);                // 消息发送完成信号

private:
    QUdpSocket *udpSocket;                                   // UDP套接字
    QString broadcastAddress;                                // 广播地址(默认255.255.255.255)
};

/**
 * 发送UDP广播消息
 * 核心逻辑:将消息转换为字节数组,发送到广播地址
 */
bool UDPSender::sendMessage(const QString &message, quint16 port)
{
    if (message.isEmpty()) {
        qDebug() << "消息内容为空,无法发送";
        return false;
    }

    QByteArray datagram = message.toUtf8();  // 转换为UTF-8字节数组
    qint64 bytesSent = udpSocket->writeDatagram(datagram, QHostAddress(broadcastAddress), port);
  
    if (bytesSent == -1) {
        qDebug() << "发送失败:" << udpSocket->errorString();
        return false;
    } else {
        qDebug() << "发送成功:" << message << "到" << broadcastAddress << ":" << port;
        emit messageSent(message);  // 发送成功信号
        return true;
    }
}

5. UDP广播接收

UDP接收器类实现广播消息接收功能:

cpp 复制代码
/**
 * UDP广播接收器类
 * 核心功能:监听指定端口,接收UDP广播消息
 */
class UDPReceiver : public QObject
{
    Q_OBJECT

public:
    explicit UDPReceiver(QObject *parent = nullptr);
    ~UDPReceiver();

    bool startListening(quint16 port);    // 开始监听指定端口
    void stopListening();                 // 停止监听
    bool isListening() const;             // 检查是否正在监听

signals:
    void messageReceived(const QString &message, const QString &senderIP, quint16 senderPort); // 接收到消息信号

private slots:
    void onReadyRead();                   // 数据可读时处理

private:
    QUdpSocket *udpSocket;                // UDP套接字
    bool listening;                       // 监听状态标志
};

/**
 * 开始监听UDP广播消息
 * 核心逻辑:绑定指定端口,等待接收UDP数据包
 */
bool UDPReceiver::startListening(quint16 port)
{
    if (listening) {
        qDebug() << "已经在监听中,请先停止当前监听";
        return false;
    }

    if (!udpSocket->bind(QHostAddress::Any, port)) {  // 绑定到任意地址和指定端口
        qDebug() << "绑定端口失败:" << udpSocket->errorString();
        return false;
    }

    listening = true;
    qDebug() << "开始监听端口:" << port;
    return true;
}

/**
 * 处理接收到的UDP数据包
 * 核心逻辑:读取数据包内容,解析发送方信息,发出接收信号
 */
void UDPReceiver::onReadyRead()
{
    while (udpSocket->hasPendingDatagrams()) {  // 处理所有待处理的数据包
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        QHostAddress senderAddress;
        quint16 senderPort;

        // 读取数据包,获取发送方地址和端口
        udpSocket->readDatagram(datagram.data(), datagram.size(), &senderAddress, &senderPort);

        QString message = QString::fromUtf8(datagram);  // 转换为UTF-8字符串
        QString senderIP = senderAddress.toString();

        qDebug() << "收到消息:" << message << "来自" << senderIP << ":" << senderPort;
        emit messageReceived(message, senderIP, senderPort);  // 发出接收信号
    }
}

6. 自动发送功能

使用QTimer实现定时自动发送功能:

cpp 复制代码
/**
 * 开始自动发送UDP广播
 * 核心逻辑:启动定时器,按指定间隔自动发送消息
 */
void MainWindow::on_startAutoSendButton_clicked()
{
    QString message = ui->messageLineEdit->text().trimmed();
    if (message.isEmpty()) {
        QMessageBox::warning(this, "警告", "请输入要发送的消息内容!");
        return;
    }
  
    int interval = ui->intervalSpinBox->value();
    autoSendTimer->start(interval);       // 启动定时器
  
    // 更新按钮状态
    ui->startAutoSendButton->setEnabled(false);
    ui->stopAutoSendButton->setEnabled(true);
    ui->sendButton->setEnabled(false);
  
    statusBar()->showMessage("开始自动发送消息");
}

/**
 * 自动发送定时器超时处理
 * 核心逻辑:定时器触发时自动发送UDP广播消息
 */
void MainWindow::autoSendTimerTimeout()
{
    QString message = ui->messageLineEdit->text().trimmed();
    if (!message.isEmpty()) {
        quint16 port = ui->sendPortSpinBox->value();
        udpSender->sendMessage(message, port);
    }
}

7. 消息处理与显示

实现消息的格式化显示和记录功能:

cpp 复制代码
/**
 * 接收UDP广播消息处理
 * 核心逻辑:格式化接收到的消息,显示发送方IP和端口信息
 */
void MainWindow::on_messageReceived(const QString &message, const QString &senderIP, quint16 senderPort)
{
    QString logMessage = QString("[接收] %1 - 来自 %2:%3")
                        .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
                        .arg(senderIP)
                        .arg(senderPort);
  
    appendMessage(message, logMessage);
    statusBar()->showMessage(QString("收到来自 %1:%2 的消息").arg(senderIP).arg(senderPort), 2000);
}

void MainWindow::on_messageSent(const QString &message)
{
    QString logMessage = QString("[发送] %1 - 本地 %2")
                        .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"))
                        .arg(localIP);
  
    appendMessage(message, logMessage);
}

void MainWindow::appendMessage(const QString &message, const QString &type, const QString &source)
{
    QString fullMessage = QString("%1\n内容: %2\n").arg(type).arg(message);
  
    // 如果消息太长,进行换行处理
    if (message.length() > 80) {
        QString formattedMessage;
        for (int i = 0; i < message.length(); i += 80) {
            formattedMessage += message.mid(i, 80) + "\n";
        }
        fullMessage = QString("%1内容:\n%2").arg(type).arg(formattedMessage);
    }
  
    ui->messageTextEdit->append(fullMessage);
  
    // 自动滚动到底部
    QTextCursor cursor = ui->messageTextEdit->textCursor();
    cursor.movePosition(QTextCursor::End);
    ui->messageTextEdit->setTextCursor(cursor);
}

项目特色

1. 模块化设计

  • UDPSender: 专门负责UDP广播发送
  • UDPReceiver: 专门负责UDP广播接收
  • MainWindow: 负责界面管理和业务逻辑协调

2. 用户友好

  • 自动检测网络接口,支持多网卡环境
  • 实时状态显示,操作反馈及时
  • 消息记录完整,便于调试和分析

3. 功能完整

  • 支持手动和自动发送
  • 支持消息监听和记录
  • 支持IP地址选择
  • 支持端口配置

编译运行

  1. 使用Qt Creator打开 07_UDPBroadcastingTool.pro项目文件
  2. 配置使用MinGW32编译器
  3. 点击构建项目(Ctrl+B)
  4. 运行程序(Ctrl+R)

使用说明

  1. 发送消息: 输入消息内容,设置发送端口,点击"发送"按钮
  2. 自动发送: 设置发送间隔,点击"开始自动发送"
  3. 接收消息: 设置监听端口,点击"开始监听"
  4. 查看记录: 在消息记录区域查看所有发送和接收的消息

技术要点

  • UDP广播: 使用255.255.255.255作为广播地址
  • 网络接口检测: 使用QNetworkInterface遍历网络接口
  • 信号槽机制: 实现组件间松耦合通信
  • 定时器应用: 使用QTimer实现自动发送功能
  • UTF-8编码: 确保中文消息的正确传输

总结

本项目是一个功能完整的UDP广播工具,展示了Qt网络编程的核心技术。通过模块化设计、信号槽机制、网络接口检测等技术,实现了一个用户友好、功能完整的网络通信工具。该项目适合学习Qt网络编程、UDP协议、信号槽机制等知识点。


作者 : [您的CSDN用户名]
项目地址 : [您的GitHub地址]
技术交流: 欢迎在评论区讨论技术问题