成都网站建设 网络公司/青岛seo外包公司
“ 所有生而孤独的人,葆有的天真 ”
为了⽀持跨平台, 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…...

【Docker项目实战】使用Docker部署MinIO对象存储(详细教程)
【Docker项目实战】使用Docker部署MinIO对象存储 前言一、 MinIO介绍1.1 MinIO简介1.2 主要特点1.3 主要使用场景二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、下载MinIO镜像五、…...

使用ollama本地部署Deepseek r1
1、下载ollama 在浏览器地址输入:https://ollama.com/ 选择windows版本的下载 2、安装ollama 3、运行ollama 安装完成后,打开命令行工具win r 在命令行输入:ollama 4、使用ollama下载并部署Deepseed r1 在ollama网站,下载…...

Unity飞行代码 超仿真 保姆级教程
本文使用Rigidbody控制飞机,基本不会穿模。 效果 飞行效果 这是一条优雅的广告 如果你也在开发飞机大战等类型的飞行游戏,欢迎在主页搜索博文并参考。 搜索词:Unity游戏(Assault空对地打击)开发。 脚本编写 首先是完整代码。 using System.Co…...

DeepSeek蒸馏模型:轻量化AI的演进与突破
目录 引言 一、知识蒸馏的技术逻辑与DeepSeek的实践 1.1 知识蒸馏的核心思想 1.2 DeepSeek的蒸馏架构设计 二、DeepSeek蒸馏模型的性能优势 2.1 效率与成本的革命性提升 2.2 性能保留的突破 2.3 场景适应性的扩展 三、应用场景与落地实践 3.1 智能客服系统的升级 3.2…...

使用 sunshine+moonlight 配置串流服务无法使用特殊键
最近了解到串流技术,使用的方案是 sunshine 为串流服务端,moonlight 为客户端,分别在 ipad,android,tv 端安装。 存在的问题 不管说什么平台都会有特殊键无法使用的问题,最初我发现在安卓电视,…...

5.角色基础移动
能帮到你的话,就给个赞吧 😘 文章目录 角色的xyz轴与移动方向拌合输入轴值add movement inputget controller rotationget right vectorget forward vector 发现模型的旋转改变后,xyz轴也会改变,所以需要旋转值来计算xyz轴方向。 …...

单细胞-第四节 多样本数据分析,下游画图
文件在单细胞\5_GC_py\1_single_cell\2_plots.Rmd 1.细胞数量条形图 rm(list ls()) library(Seurat) load("seu.obj.Rdata")dat as.data.frame(table(Idents(seu.obj))) dat$label paste(dat$Var1,dat$Freq,sep ":") head(dat) library(ggplot2) lib…...

Linux的循环,bash的循环
Linux的循环,bash的循环 在 Linux 系统中,Bash 循环是最常用的循环实现方式(Bash 是 Linux 默认的 Shell),但广义上“Linux 的循环”可能涉及其他 Shell 或编程语言的循环结构。以下是 Bash 循环的详细解析及其在 Linux 环境中的…...

【DeepSeek开发】Python实现股票数据可视化
代码: Github:Python实现股票数据可视化代码https://github.com/magolan2000/Data-visualization/tree/master 软件环境:PyCharm 2022.3.1 数据来源:akshare 最近DeepSeek可谓是热度不断,因此想评判一下DeepSeek的编程…...

华为小米vivo向上,苹果荣耀OPPO向下
日前,Counterpoint发布的手机销量月度报告显示,中国智能手机销量在2024年第四季度同比下降3.2%,成为2024年唯一出现同比下滑的季度。而对于各大智能手机品牌来说,他们的市场份额和格局也在悄然发生变化。 华为逆势向上 在2024年第…...