Qt网络相关

“ 所有生而孤独的人,葆有的天真 ”
为了⽀持跨平台, QT对⽹络编程的 API 也进⾏了重新封装。本章会上手一套基于QT的网络通信编写。
UDP Socket
在使用Qt进行网络编程前,需要在Qt项目中的.pro文件里添加对应的网络模块( network ).
QT += core gui network
QUdpsocket 核心API
| 名称 | 类型 | 说明 | 原⽣ API |
| bind(const QHostAddress&, quint16) | 方法 | 绑定指定的端⼝号 | bind |
| receiveDatagram() | ⽅法 | 返回 QNetworkDatagram . 读取 ⼀个 UDP 数据报. | recvfrom |
| writeDatagram(const QNetworkDatagram&) | ⽅法 | 发送⼀个 UDP 数据报. | sendto |
| readyRead | 信号 | 在收到数据并准备就绪后触发 | |
| QNetworkDatagram(const QByteArray&, const QHostAddress& , quint16 ) | 构造函数 | ||
| data() | ⽅法 | 获取数据报内部持有的数据. 返回QByteArray | |
| senderAddress() | ⽅法 | 获取对端的 IP 地址. | |
| senderPort() | ⽅法 | 获取对端的端⼝号 |
基于udp的简单回显程序
· 服务端
🎃 创建界面,包含一个 QListWidget 用于显示消息

🎃 在主类中,创建QUdpSocket成员

🎃 进行初始化
// 1. 设置窗口标题this->setWindowTitle("服务器");// 2. 实例化socket = new QUdpSocket(this);// 3. 连接信号槽, 处理收到的请求connect(socket,&QUdpSocket::readyRead,this,&MainWindow::processRequest);// 4. 端口bind(ip,port)bool ret = socket->bind(QHostAddress::Any,9090);if(ret == false){QMessageBox::critical(nullptr,"服务器启动错误",socket->errorString());return;}
一般来说,都是先建立信号与槽的连接,再进行网络端口的绑定。如果顺序反过来,当网络端口进行bind后,客户端就可以发送来消息处理,此时如果没来得及连接信号槽,为这个请求提供的服务就可能失效。
🎃 槽函数实现(实现对端消息的回显功能)
QString MainWindow::process(const QString & req)
{return req;
}void MainWindow::processRequest()
{// 当走到这里 说明服务器已经收到对端信息递达的信号 触发的槽函数处理~// 1.获取请求const QNetworkDatagram& requestDatagram = socket->receiveDatagram();// QNetworkDatagram.data() 拿到对端请求的原始数据QString request = requestDatagram.data();// 2. 计算处理请求const QString& response = process(request);// 3.把响应写回到客⼾端QNetworkDatagram responseDatagram(response.toUtf8(),\requestDatagram.senderAddress(),requestDatagram.senderPort());socket->writeDatagram(responseDatagram);// 4.显示打印日志QString log = "[" + requestDatagram.senderAddress().toString() + ":" +QString::number(requestDatagram.senderPort()) + "]" + " " + "req: " + request + " | " + "resp: " + response;ui->listWidget->addItem(log);
}
· 客户端
🧧 创建一个界面,包含用户发送消息窗口、发送按钮、输入栏。发送窗口仍然使用QListWidget,依次是pushButton、QLineEdit。

先使⽤⽔平布局( layout) 把两个控件齐整。

进入到控件中的sizePolicy 设置为 “Expanding ”。 接着再使用垂直布局,将消息发送窗口与水平布局的两个空间再进行空间管理。当然我们需要在垂直布局中设置比例,否则比较难看~

这样,简易的界面也算完成了。
🧧 初始化IP和端口
在mainwindows.h中定义两个静态变量
static const QString& server_ip = "127.0.0.1";
static const quint16 server_port = 9090;
void MainWindow::on_send_putton_clicked()
{// 1. 获取输入的内容const QString& text = ui->message_edit->text();// 2. 利用text构造数据报QNetworkDatagram requestDatagram = \QNetworkDatagram(text.toUtf8(),QHostAddress(server_ip),server_port);// 3.发送请求socket->writeDatagram(requestDatagram);// 4.前端回显ui->message_screen->addItem("客户端说: " + text);// 5.每发完一条消息 清空输入框ui->message_edit->clear();
}
🧧 接收客户端回显(槽函数)
// 接收服务端回显connect(socket,&QUdpSocket::readyRead,this,[=](){const QNetworkDatagram responseDatagram = socket->receiveDatagram();QString resp = responseDatagram.data();ui->message_screen->addItem(QString("服务器回显: " + resp));});
TCP Socket
TCP相对于UDP而言要复杂很多,只要你曾学过网络知识。我们首先来了解了解Tcp Socket中的核心API。
QTcpServer 核心API
| 名称 | 类型 | 说明 | 对标原⽣ API |
| listen(const QHostAddress&, quint16 port) | 方法 | 绑定指定的地址和端⼝号, 并开始监听 | bind 和 listen |
| nextPendingConnection() | 方法 | 从系统中获取到⼀个已经建⽴好的 tcp 连接. 返回⼀个 QTcpSocket , 表⽰这个 客⼾端的连接. | accept |
| newConnection() | 信号 | 有新的客⼾端建⽴连接好之后触发 | |
| readAll() | 方法 | 读取当前接收缓冲区中的所有数据. 返回 QByteArray 对象 | read |
| write(const QByteArray& ) | 方法 | 把数据写⼊ socket 中 | write |
| readyRead | 信号 | 有数据到达并准备就绪时触发 | |
| deleteLater() | 方法 | 暂时把 socket 对象标记为⽆效. | |
| disconnected() | 信号 | 连接断开时触发 |
想对比于udp的核心API,我们会发现没有了于 "Datagram" 相关的任何接口了。这本质是因为TCP是面向字节流而非udp那样的数据报。
基于TCP的简单回显程序
因为都是做回显,那么这里服务器、客户端的前端依旧同udp是一的 ~
· 服务端
🎨 编写QTcpServer
#include <QMainWindow>
#include <QString>
#include <QTcpServer>
#include <QHostAddress>
#include <QMessageBox>
#include <QTcpSocket>// 设置窗口信息this->setWindowTitle(" 服务器 ");// 1.实例化tcpserver = new QTcpServer(this);// 2.通过信号槽, 处理客⼾端建⽴的新连接.connect(tcpserver,&QTcpServer::newConnection,this,&MainWindow::processConnection);// 3.监听+bindbool ret = tcpserver->listen(QHostAddress::Any,9090);if(ret == false){QMessageBox::critical(nullptr,"服务器启动失败",tcpserver->errorString());exit(-1);}
🎨 继续修改 widget.cpp, 实现处理连接的具体⽅法processConnection
void MainWindow::processConnection()
{// 1.根据 listen 获取接收到的新连接// 注: 这里是 "QTcpSocket"QTcpSocket* clientsocket = tcpserver->nextPendingConnection();// 更新服务端日志QString log = QString("[") + clientsocket->peerAddress().toString() + ":" + \QString::number(clientsocket->peerPort()) + "] 客户端上线";ui->listWidget->addItem(log);
}
🎨 完成回显工作(槽函数实现)
可以发现,不管是做udp还是tcp的网络模型服务,我们都舍弃了用循环的方式处理请求。这会导致我们,一旦存在占用资源的连接不及时释放cpu资源,那么别的请求就不会被读取到,直到该请求的任务执行完成。
Qt中的槽机制恰好避免了这样的困境,一旦发出信号,就执行槽函数即可~
// 信号槽处理 处理收到请求的情况connect(clientsocket,&QTcpSocket::readyRead,this,[=](){// 字节流 把所有字节都 读上来const QString req = clientsocket->readAll();// 根据请求 制作响应const QString& resp = process(req);// 写回客户端clientsocket->write(resp.toUtf8());// 服务端回显QString log = "[" + clientsocket->peerAddress().toString() + ":" + QString::number(clientsocket->peerPort()) \+ "]" + " " + "req: " + req;ui->listWidget->addItem(log);});
由于Tcp可靠性的特征,每一次客户端的连接都会被服务端保存着。当客户端断开连接时而服务端并不是释放两者之间用于连接的资源时,就会导致 资源泄漏~~
// 通过信号槽, 处理断开连接的情况connect(clientsocket,&QTcpSocket::disconnected,this,[=](){QString log = QString("[") + clientsocket->peerAddress().toString() + ":" + \QString::number(clientsocket->peerPort()) + "] 客户端下线";ui->listWidget->addItem(log);// 释放资源clientsocket->deleteLater(); // 并不会立即释放});
· 客户端
👑 初始化mainwindow.cpp
this->setWindowTitle("客户端");// 1. 实例化socketsocket = new QTcpSocket(this);// 2. 建立连接socket->connectToHost("127.0.0.1",9090);// 3.等待并确认连接是否出错bool ret = socket->waitForConnected();if(ret == false){QMessageBox::critical(nullptr,"连接失败",socket->errorString());exit(-1);}
👑 给按钮增加点击的 slot 函数, 实现发送请求给服务器
void MainWindow::on_send_clicked()
{// 获得输入的内容 并输出在界面上const QString& text = ui->edit->text();ui->edit->clear();ui->messageScreen->addItem("已发送: " + text);// 真正的发送消息socket->write(text.toUtf8());
}
connect(socket,&QTcpSocket::readyRead,this,[=](){QString resp = socket->readAll();qDebug() << resp;ui->messageScreen->addItem("服务端回显: " + resp);});
测试:

不管是响应还是,当客户端断开连接时,我们都能够完成对应的功能。
HTTP
进⾏ Qt 开发时, 和服务器之间的通信很多时候也会⽤到 HTTP 协议。我们大概需要以下几个步骤:
• 通过 HTTP 从服务器获取数据.• 通过 HTTP 向服务器提交数据.
核心API
关键类有三个 QNetworkAccessManager、QNetworkRequest、QNetworkReply .
| ⽅法 | 说明 |
| get(const QNetworkRequest& ) | 发起⼀个 HTTP GET 请求. 返回 QNetworkReply 对象. |
| post(const QNetworkRequest& , const QByteArray& ) | 发起⼀个 HTTP POST 请求. 返回 QNetworkReply 对 象. |
🏀 QNetworkRequest 表⽰⼀个 HTTP 请求.
如果需要发送⼀个带有 body 的请求(⽐如 post), 会在 QNetworkAccessManager 的 post ⽅法 中通过单独的参数来传⼊ body.
| ⽅法 | 说明 |
| QNetworkRequest(const QUrl&) | 通过 URL 构造⼀个 HTTP 请求. |
| setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value) | 设置请求头. |
🏀 QNetworkRequest::KnownHeaders 是⼀个枚举类型
| ⽅法 | 说明 |
| ContentTypeHeader | 描述 body 的类型 |
| ContentLengthHeader | 描述 body 的⻓度. |
| LocationHeader | ⽤于重定向报⽂中指定重定向地址 |
| CookieHeader | 设置 cookie |
| UserAgentHeader | 设置请求头. |
| ⽅法 | 说明 |
| error() | 获取出错状态. |
| errorString() | 获取出错原因的⽂本. |
| readAll() | 读取响应 body |
| header(QNetworkRequest::KnownHeaders header) | 设置 cookie |
构建一个Http客户端
因为我们只需要构建一个模拟的HTTP请求。服务端则不需要我们进行什么编写~~
QPlainTextEdit vs QTextEdit
QTextEdit会进⾏富 ⽂本解析, 如果得到的 HTTP 响应体积很⼤, 就会导致界⾯渲染缓慢甚⾄被卡住。
🏐 修改 mainwindow.h, 创建 QNetworkAccessManager 属性
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>QNetworkAccessManager* manager;
🏐 创建实例并初始化
this->setWindowTitle(" Http请求发起器 ");// 1. 实例初始化manager = new QNetworkAccessManager(this);
void MainWindow::on_pushButton_clicked()
{// 1. 根据输入框里url,构造QurlQUrl url(ui->lineEdit->text());// 2. 构造http响应QNetworkRequest req(url);// 3. 以什么方法访问QNetworkReply* resp = manager->get(req);// 通过信号槽来处理响应connect(resp,&QNetworkReply::finished,this,[=](){if(resp->error() == QNetworkReply::NoError){QString html(resp->readAll());ui->plainTextEdit->setPlainText(html);}else{ui->plainTextEdit->setPlainText(resp->errorString());}resp->deleteLater();});
}
本篇到此结束,感谢你的阅读。
祝你好运,向阳而生~

相关文章:
Qt网络相关
“ 所有生而孤独的人,葆有的天真 ” 为了⽀持跨平台, QT对⽹络编程的 API 也进⾏了重新封装。本章会上手一套基于QT的网络通信编写。 UDP Socket 在使用Qt进行网络编程前,需要在Qt项目中的.pro文件里添加对应的网络模块( network ). QT core gui net…...
deepseek接入pycharm 进行AI编程
要将DeepSeek接入PyCharm进行AI编程,可以按照以下步骤操作: ### 1. 获取DeepSeek API访问权限 DeepSeek通常以API的形式对外提供服务,你需要在其官方网站注册账号,申请API访问权限。在申请通过后,会获得API密钥(API Key),这是后续调用API的关键凭证。 ### 2. 安装必要…...
Verilog基础(三):过程
过程(Procedures) - Always块 – 组合逻辑 (Always blocks – Combinational) 由于数字电路是由电线相连的逻辑门组成的,所以任何电路都可以表示为模块和赋值语句的某种组合. 然而,有时这不是描述电路最方便的方法. 两种always block是十分有用的&am…...
生成式AI安全最佳实践 - 抵御OWASP Top 10攻击 (上)
今天小李哥将开启全新的技术分享系列,为大家介绍生成式AI的安全解决方案设计方法和最佳实践。近年来,生成式 AI 安全市场正迅速发展。据 IDC 预测,到 2025 年全球 AI 安全解决方案市场规模将突破 200 亿美元,年复合增长率超过 30%…...
.Net WebAPI -[HttpPut(“{fileServiceId:int}“)]
[HttpPut("{fileServiceId:int}")] 这个写法是 ASP.NET Core 中的一个路由特性,用于定义一个 HTTP PUT 请求的路由,并指定路由参数的类型。 解析 HttpPut [HttpPut]: 这是一个 ASP.NET Core 的路由特性,用于标记一个方…...
[EAI-027] RDT-1B,目前最大的用于机器人双臂操作的机器人基础模型
Paper Card 论文标题:RDT-1B: a Diffusion Foundation Model for Bimanual Manipulation 论文作者:Songming Liu, Lingxuan Wu, Bangguo Li, Hengkai Tan, Huayu Chen, Zhengyi Wang, Ke Xu, Hang Su, Jun Zhu 论文链接:https://arxiv.org/ab…...
C基础寒假练习(7)
一、有 1、2、3、4个数字,能组成多少互不相同且无重复的三位? 都是多少? #include <stdio.h> int main() {// 定义数字数组int digits[] {1, 2, 3, 4};int n sizeof(digits) / sizeof(digits[0]);// 嵌套循环遍历所有排列for (int …...
Ajax:重塑Web交互体验的人性化探索
在数字化时代,网页的交互性和响应速度已成为衡量用户体验的关键指标。Ajax(Asynchronous JavaScript and XML),作为前端与后端沟通的桥梁,凭借其异步通信的能力,极大地提升了网页的动态性和用户友好度&…...
【DeepSeek背后的技术】系列二:大模型知识蒸馏(Knowledge Distillation)
目录 1 引言2 操作步骤和公式说明2.1 准备教师模型(Teacher Model)和学生模型(Student Model)2.2 生成软标签(Soft Labels)2.3 定义蒸馏损失函数2.4 训练学生模型2.5 调整超参数2.6 评估与部署 3 其他知识蒸…...
【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.14 内存映射:处理超大型数组的终极方案
2.14 内存映射:处理超大型数组的终极方案 目录 #mermaid-svg-G91Kn9O4eN2k8xEo {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-G91Kn9O4eN2k8xEo .error-icon{fill:#552222;}#mermaid-svg-G91Kn9O4eN2k…...
【C++】STL——vector的使用
目录 💕1.vector介绍 💕2.vector的基本用法 💕3.vector功能的具体用法 (讲解) 💕4.vector——size,capacity函数的使用 (简单略讲) 💕5.resizeÿ…...
springboot/ssm互联网智慧医院体检平台web健康体检管理系统Java代码编写
springboot/ssm互联网智慧医院体检平台web健康体检管理系统Java代码编写 基于springboot(可改ssm)vue项目 开发语言:Java 框架:springboot/可改ssm vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库&am…...
介绍一下Mybatis的Executor执行器
Executor执行器是用来执行我们的具体的SQL操作的 有三种基本的Executor执行器: SimpleExecutor简单执行器 每执行一次update或select,就创建一个Statement对象,用完立刻关闭Statement对象 ReuseExecutor可重用执行器 可重复利用Statement…...
Wide Deep 模型:记忆能力与泛化能力
实验和完整代码 完整代码实现和jupyter运行:https://github.com/Myolive-Lin/RecSys--deep-learning-recommendation-system/tree/main 引言 Wide & Deep 模型是一种结合了线性模型(Wide)和深度神经网络(Deep)的混…...
Hot100之矩阵
73矩阵置零 题目 思路解析 收集0位置所在的行和列 然后该行全部初始化为0 该列全部初始化为0 代码 class Solution {public void setZeroes(int[][] matrix) {int m matrix.length;int n matrix[0].length;List<Integer> list1 new ArrayList<>();List<…...
Python语言的安全开发
Python语言的安全开发 引言 在信息技术迅速发展的今天,网络安全问题愈发凸显。随着Python语言的广泛应用,尤其是在数据分析、人工智能、Web开发等领域,其安全问题越来越受到重视。Python作为一门高效且易于学习的编程语言,虽然在…...
蓝桥杯刷题DAY3:Horner 法则 前缀和+差分数组 贪心
所谓刷题,最重要的就是细心 📌 题目描述 在 X 进制 中,每一数位的进制不固定。例如: 最低位 采用 2 进制,第二位 采用 10 进制,第三位 采用 8 进制, 则 X 进制数 321 的十进制值为ÿ…...
java项目验证码登录
1.依赖 导入hutool工具包用于创建验证码 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.5.2</version></dependency> 2.测试 生成一个验证码图片(生成的图片浏览器可…...
手写MVVM框架-环境搭建
项目使用 webpack 进行进行构建,初始化步骤如下: 1.创建npm项目执行npm init 一直下一步就行 2.安装webpack、webpack-cli、webpack-dev-server,html-webpack-plugin npm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin 3.配置webpac…...
2025年2月2日(网络编程 tcp)
tcp 循环服务 import socketdef main():# 创建 socket# 绑定tcp_server socket.socket(socket.AF_INET, socket.SOCK_STREAM)tcp_server.bind(("", 8080))# socket 转变为被动tcp_server.listen(128)while True:# 产生专门为链接进来的客户端服务的 socketprint(&qu…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
