【Qt】Qt 网络 | UDP Socket

文章目录

要使用 Qt 网络编程,需要在项目中的 .pro 文件中添加 network 模块

核心API

Qt 的 UDP Socket 主要的类有两个 QUdpSocketQNetworkDatagram

因为是 UDP 是面向数据报的,QNetworkDatagram 就是对 数据报的封装,内容包括:对端发送的数据,对端的 IP 和 端口号

QUdpSocket 表示一个 UDP 的 socket 文件

名称 类型 说明 对标原生API
bind(const QHostAddress &address, quint16 port = 0) 方法 绑定指定的 IP地址 和 端口号 bind
receiveDatagram() 方法 返回 QNetworkDatagram 读取一个 UDP 数据报 recvfrom
writeDatagram(const QNetworkDatagram &datagram) 方法 发送一个 UDP 数据报 sendto
writeDatagram(const char *data, qint64 size, const HostAddress &address, quint16 port) 方法 data是要发送的数据,size是数据的长度,address是目标 IP地址,port是目标端口号 sendto
readyRead 信号 在收到数据并准备就绪后触发 类似于 IO 多路复用的通知机制

QNetworkDatagram 表示一个 UDP 数据报

名称 类型 说明 对标原生API
QNetworkDatagram(const QByteArray &data, const QHostAddress &destinationAddress = QHostAddress(), quint16 port = 0) 构造函数 通过 QByteArray,目标 IP地址,目标端口号构造一个 UDP 数据报,通常用于发送数据
data() 方法 获取数据报内部持有的数据,返回 QByteArray
senderAddress() 方法 获取数据报中包含的对端的IP地址 recvfrom 包含了该功能
senderPort() 方法 获取数据报中包含的对端的端口号 recvfrom 包含了该功能

代码示例

通过模拟 客户服务器的UDP通信 熟悉上述方法使用

客户端通过输入栏获取数据,点击按钮发送给服务端

服务端接受客户端数据,并返回相同数据,验证通信无误

服务器

  1. 创建界面,包含一个 QListWidget 用来显示消息
  2. 创建 QUdpSocket 成员,修改 widget.h
cpp 复制代码
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
//槽函数
public slots:
    void handleRequest();//处理客户端请求
private:
    QString process(const QString &request);//业务处理逻辑
private:
    Ui::Widget *ui;
    QUdpSocket *socket;//套接字
};
  1. 编写 widget.cpp,实现相关方法

因为 UDP 是无连接的,绑定端口号后就可以接受数据了,所以要先对 readReady信号连接槽函数

逻辑如下:1. 设置窗口标题 2. 创建套接字 3. 连接信号槽 4. 绑定端口号

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //1. 设置窗口标题
    this->setWindowTitle("服务端");
    //2. 创建套接字
    socket = new QUdpSocket(this);
    //UDP绑定完就开启服务了,所以需要先连接信号槽
    //3. 连接信号槽
    connect(socket, &QUdpSocket::readyRead, this, &Widget::handleRequest);
    //4. 绑定,服务端绑定任意IP,端口号指定为9090
    bool ret = socket->bind(QHostAddress::Any, 9090);
    if(!ret)
    {
        QMessageBox::critical(this, "错误", "绑定套接字失败");
        return;
    }

}

编写 readReady 对应槽函数

逻辑如下:1. 获取用户数据报 2. 提取其中数据 3. 业务处理 4. 返回响应

cpp 复制代码
void Widget::handleRequest()
{
    //1. 获取用户数据报
    const QNetworkDatagram requestDatagram = socket->receiveDatagram();
    //2. 提取其中数据
    QString request = requestDatagram.data();
    //3. 业务处理逻辑
    QString responce = process(request);
    //4. 记录客户端数据
    QString log = "[" + requestDatagram.senderAddress().toString() + ":" + QString::number(requestDatagram.senderPort())
                + "]  request:" + request + "  responce:" + responce;
    ui->listWidget->addItem(log);
    //5. 返回响应
    QNetworkDatagram responceDatagram(responce.toUtf8(), requestDatagram.senderAddress(), requestDatagram.senderPort());
    socket->writeDatagram(responceDatagram);
}

此处服务器的业务处理只是简单的回显数据

cpp 复制代码
QString Widget::process(const QString &request)
{
    return request;
}

客户端

  1. 创建界面。包含 一个 QLineEditQPushButtonQListWidget
    通过布局管理器搭配,规范界面
  2. 声明全局常量:服务端的 IP地址端口号
cpp 复制代码
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 9090
  1. 创建 QUdpSocket 成员,修改 widget.h,定义成员
cpp 复制代码
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
private slots:
    //按钮点击槽函数
    void on_pushButton_clicked();
    //客户端业务处理逻辑
    void handleRequest();
private:
    Ui::Widget *ui;
    QUdpSocket *socket;
};
  1. 修改 widget.cpp,初始化 socket
    客户端不需要绑定端口号
cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->pushButton->setShortcut(QKeySequence(Qt::Key_Return));
    //设置窗口标题
    this->setWindowTitle("客户端");
    //创建套接字
    socket = new QUdpSocket(this);
    //连接信号槽
    connect(socket, &QUdpSocket::readyRead, this, &Widget::handleRequest);
}

按钮点击槽函数

逻辑如下:1. 获取输入栏文本 2. 记录发送信息 3. 将消息发送给服务端 4. 清空输入栏

cpp 复制代码
void Widget::on_pushButton_clicked()
{
    //1. 获取输入栏的文本
    QString text = ui->lineEdit->text();
    QNetworkDatagram requestDatagram(text.toUtf8(), QHostAddress(SERVER_IP), SERVER_PORT);
    //2. 记录发送信息
    QString message = "发送:" + text;
    ui->listWidget->addItem(message);
    //3. 将消息发送给服务端
    socket->writeDatagram(requestDatagram);
    //4. 将输入栏清空
    ui->lineEdit->clear();
}

客户端业务处理函数

cpp 复制代码
void Widget::handleRequest()
{
    //1. 获取服务端返回的数据报
    QNetworkDatagram responceDatagram = socket->receiveDatagram();
    QString responce = responceDatagram.data();
    //2. 显示消息
    ui->listWidget->addItem("接收:" + responce);
}

运行结果如下:

结束语

感谢你的阅读

如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。

相关推荐
红尘客栈213 分钟前
Kubernetes 集群调度
java·linux·网络·容器·kubernetes
aodunsoft23 分钟前
安全月报 | 傲盾DDoS攻击防御2025年9月简报
网络·安全·ddos
杂化轨道VSEPR33 分钟前
基站计数器与KPI:移动通信网络性能评估的核心引擎
运维·服务器·网络·5g·信息与通信
小张数码34 分钟前
随身WiFi技术深探:通信芯片/信号增益原理解析+开源方案参考!随身WiFi建议买吗?随身WiFi品牌哪个网速快信号稳定?格行随身WiFi怎么样?
网络·物联网
CoderCodingNo34 分钟前
【GESP】C++五级考试大纲知识点梳理, (3-4) 链表-双向循环链表
开发语言·c++·链表
Starry_hello world34 分钟前
Linux 进程地址空间
linux·笔记·有问必答
撬动未来的支点1 小时前
【Linux】Linux驱动开发与BSP开发:嵌入式系统的两大基石
linux·驱动开发
colus_SEU1 小时前
【编译原理笔记】2.1 Programming Language Basics
c++·算法·编译原理
jz_ddk1 小时前
[LVGL] 从0开始,学LVGL:基础构建篇 - 掌握UI的核心构建块
linux·网络协议·ui·rpc·嵌入式·gui·lvgl
liu****1 小时前
笔试强训(二)
开发语言·数据结构·c++·算法·哈希算法