当前位置: 首页 > news >正文

Qt网络编程——QTcpServer和QTcpSocket

文章目录

    • 核心API
    • TCP回显服务器
    • TCP回显客户端

核心API

QTcpServer用于监听端口和获取客户端连接

名称类型说明对标原生API
listen(const QHostAddress&, quint16 port)方法绑定指定的地址和端口号,并开始监听bind和listen
nextPendingConnection()方法从系统中获取到一个建立好的tcp连接
返回一个QTcpSocket,表示这个客户端的连接
通过这个socket对象完成和客户端之间的通信
accept
newCondition()信号有新的客户端建立好连接之后触发无(类似IO多路复用的通知机制)

QTcpSocket用于客户端和服务器之前的数据交互

tcp读取的数据是字节流,因此读取和返回的都是字节数组,这和udp的QNetworkDatagram数据报不一样

事件循环,可以简单理解为是Qt程序内部一个带有“生物钟”这样的东西,周期性执行一些逻辑

名称类型说明对标原生API
readAll()方法读取当前接收缓冲区的所有数据
返回QByteArray对象
read
write(const QByteArray&)方法将数据写入socket当中write
deleteLater方法暂时把socket对象标记为无效
Qt会在下一个事件循环中构造释放该对象
readyRead信号有数据到达并准备就绪时触发
disconnected信号连接断开时触发

QByteArray是字节数组,可以和QString互相转换

  • QString的构造函数可以把QByteArray转换成QString
  • QStringtoUtf8函数可以把QString转成QByteArray

TCP回显服务器

用这些接口,写一个回显服务器。

创建项目之后,如果要进行网络编程,第一步就是在.pro文件中加入network模块

image-20240925220250317

界面:

image-20240925220340130

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpServer>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void processConnection();QString process(const QString request);
private:Ui::Widget *ui;QTcpServer *tcpServer;
};
#endif // WIDGET_H

widget.cpp

  • 绑定和监听端口号一定是要等准备工作做完之后再进行,比如说如何处理连接、如何处理请求等…

  • 需要手动释放clientSocket,因为它是每个客户端都有这样一个对象,而QTcpServerQUdpServer都是只有一份。如果不对断开连接的客户端进行释放,累计的客户端会越来越多,这会导致两个问题:文件描述符泄漏内存泄漏

    也不能直接delete clientSocket,因为当前槽函数主要是围绕clientSocket来进行操作的,一旦delete,其他逻辑就无法使用clientSocket,使用要保证delete操作是最后一步,而且不会被return或者抛出异常给跳过。

    Qt提供了deleteLater,不是立即销毁,而是告诉Qt,下一轮事件循环中,再进行上述销毁操作。

    槽函数是在事件循环中进行的,进入下一轮事件循环表明上一轮事件肯定结束了。

#include "widget.h"
#include "ui_widget.h"
#include<QMessageBox>
#include<QTcpSocket>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//修改窗口标题this->setWindowTitle("tcp服务器");//创建QTcpServer实例tcpServer = new QTcpServer(this);//连接信号槽(如何处理连接)connect(tcpServer, &QTcpServer::newConnection, this, &Widget::processConnection);//绑定并监听端口号if(!tcpServer->listen(QHostAddress::Any, 8080)){QMessageBox::critical(this, "服务器启动失败", tcpServer->errorString());return;}
}Widget::~Widget()
{delete ui;
}void Widget::processConnection()
{//拿到socket对象QTcpSocket *clientSocket = tcpServer->nextPendingConnection();//peerAddress表示对端的ip地址QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort()) + "] online";//显示到界面ui->listWidget->addItem(log);//通过信号槽处理客户端发来的请求connect(clientSocket, &QTcpSocket::readyRead, this, [=](){//读取请求QString request = clientSocket->readAll();//处理请求const QString &response = process(request);//返回响应clientSocket->write(response.toUtf8());//记录日志QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort()) + "]"+ "req: " + request + ", resp: " + response;ui->listWidget->addItem(log);});//客户端断开连接//disconnected表示已经断开,是一个信号connect(clientSocket, &QTcpSocket::disconnected, this, [=](){QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort()) + "] offline";ui->listWidget->addItem(log);//手动释放clientSocketclientSocket->deleteLater();});
}QString Widget::process(const QString request)
{return request;
}

此段代码,从某种意义上来说,不够严谨,因为tcp是面向字节流的,可能会分为多段。

更好的做法是,将收到的数据,放到一个较大字节的缓冲区当中,然后按照约定好的协议,进行数据解析提取。

TCP回显客户端

ui界面:

image-20240925225359499

对于客户端,使用的就是QTcpSocketQTcpServer只是在服务端使用的

  • 调用connectToHost函数,此时系统就开始和对方服务器三次握手,三次握手也是需要时间的,而这个函数并不会阻塞等待握手完毕,是一个非阻塞的函数。
    所以需要搭配waitForConnected,等待连接建立成功
#include "widget.h"
#include "ui_widget.h"
#include<QMessageBox>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//设置窗口标题this->setWindowTitle("客户端");//创建socket对象实例socket = new QTcpSocket(this);//和服务器建立连接socket->connectToHost("127.0.0.1", 8080);//连接信号槽connect(socket, &QTcpSocket::readyRead, this, [=](){//读取响应内容QString response = socket->readAll();//响应内容显示到界面ui->listWidget->addItem("server say# " + response);});//等待连接建立结果if(!socket->waitForConnected()){QMessageBox::critical(this, "连接服务器失败", socket->errorString());return;}}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{//获取输入框内容const QString &text = ui->lineEdit->text();//发送到服务器socket->write(text.toUtf8());//将发送的消息显示到界面ui->listWidget->addItem("client say#" + text);//清空输入框内容ui->lineEdit->setText("");
}

在这里插入图片描述

Linux当中写Tcp服务器的时候,如果多个客户端同时访问,就只会生效一个,然后引入线程,每个客户端一个线程;

而这里并没有出现这类情况,这是因为之前是写的两层循环,里面的循环没有结束,导致外层循环不能快速调用到accpet,导致第二个客户端无法进行处理。

引入多线程,本质上就是将双重循环,化简成两个独立的循环。

Qt里面的信号槽机制,就无需写这些循环,比较方便。

相关文章:

Qt网络编程——QTcpServer和QTcpSocket

文章目录 核心APITCP回显服务器TCP回显客户端 核心API QTcpServer用于监听端口和获取客户端连接 名称类型说明对标原生APIlisten(const QHostAddress&, quint16 port)方法绑定指定的地址和端口号&#xff0c;并开始监听bind和listennextPendingConnection()方法从系统中获…...

CentOS 7 aarch64制作openssh 9.9p1 rpm包 —— 筑梦之路

本篇文章还是基于开源项目openssh-rpms制作。 https://github.com/boypt/openssh-rpms.git 官方发行说明&#xff1a; OpenSSH: Release Notes 1. 修改version.env 2. 下载源码包 openssl网站改版&#xff0c;下载地址和之前不一样了 # 下载openssl1.1.1w源码包cd downlo…...

Flink和Spark的区别

1、设计理念不同 flink&#xff1a;Flink是基于事件驱动的&#xff0c;是面向流的处理框架, Flink基于每个事件一行一行地流式处理&#xff0c;是真正的流式计算. 另外他也可以基于流来模拟批进行计算实现批处理。 spark&#xff1a;Spark的技术理念是使用微批来模拟流的计算,…...

以太网开发基础-MAC和PHY

直接参考&#xff1a; 以太网基础-MAC和PHY-CSDN博客 路由器上一般有三类MAC地址 给一个范例: 00:0C:E5:4B:F2:85 这个地址就可以作为LAN MAC地址 00:0C:E5:4B:F2:86 这个地址就可以作为WAN MAC地址 00:0C:E5:4B:F2:87 这个地址就可以作为无线 MAC地址 通常&#xff0c;路由器…...

Java 发布jar包到maven中央仓库(2024年9月保姆级教程)

文章目录 前言一、账号准备1. 注册登录账号2. 新建命名空间3. 验证命名空间4. 生成令牌5. 为 maven 设置令牌二、GPG准备1. 下载GPG2. 发布证书2.1 新建证书2.2 发布证书到服务器2.3 验证发布三、发布jar包到中央仓库1. 编辑项目pom文件2. 打包上传3. 发布jar包4. 搜索我们的ja…...

Pandas和Seaborn可视化详解

1.Pandas绘图-单变量 概述 pandas库是Python数据分析的核心库 它不仅可以加载和转换数据&#xff0c;还可以做更多的事情&#xff1a;它还可以可视化 pandas绘图API简单易用&#xff0c;是pandas流行的重要原因之一 可视化小技巧: 如果是类别型 柱状 饼图 (类别相对较少 5-…...

【Python】Windows下安装使用FFmpeg

FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。之前为了MP3转wav&#xff0c;需要pip安装并import AudioSegment&#xff0c;但是会报错&#xff1a;FileNotFoundError: [WinError 2] 系统找不到指定的文件。 因为FFmpeg需要另…...

LLM - 使用 XTuner 指令微调 多模态大语言模型(InternVL2) 教程

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/142528967 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 XTuner…...

【Python】数据可视化之热力图

热力图&#xff08;Heatmap&#xff09;是一种通过颜色深浅来展示数据分布、密度和强度等信息的可视化图表。它通过对色块着色来反映数据特征&#xff0c;使用户能够直观地理解数据模式&#xff0c;发现规律&#xff0c;并作出决策。 目录 基本原理 sns.heatmap 代码实现 基…...

个人博客系统测试(selenium)

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;Yan. yan.                        …...

【速成Redis】01 Redis简介及windows上如何安装redis

前言&#xff1a; 适用于&#xff1a;需要快速掌握redis技能的人&#xff08;比如我&#xff09;&#xff0c;在b站&#xff0c;找了个课看。 01.课程简介_哔哩哔哩_bilibili01.课程简介是【GeekHour】一小时Redis教程的第1集视频&#xff0c;该合集共计19集&#xff0c;视频…...

入侵检测系统(IDS)和入侵预防系统(IPS)

入侵检测系统&#xff08;IDS&#xff09;和入侵预防系统&#xff08;IPS&#xff09;是网络安全领域中用来检测和防止潜在的恶意活动或政策违规行为的系统。它们的主要目的是保护网络和主机不受未授权访问和各种形式的攻击。以下是它们的主要区别和功能&#xff1a; 一&#…...

pytorch 加载模型参数后 如何测试数据,应用模型预测数据,然后连续变量转换成 list 或者numpy.array padans并保存到csv文件中

在PyTorch中&#xff0c;加载模型参数后测试数据通常涉及以下几个步骤&#xff1a; 1. **加载模型**&#xff1a;首先&#xff0c;你需要定义模型的结构&#xff0c;然后加载预训练的参数。 2. **加载数据**&#xff1a;准备你的测试数据集。确保数据集已经正确地预处理&…...

uni-app开发流程(开发、预览、构建和发布过程)

uni-app 是一个使用 Vue.js 开发所有前端应用的框架&#xff0c;支持编写一次代码&#xff0c;生成可以在多个平台&#xff08;如微信小程序、H5、App等&#xff09;运行的应用。下面是 uni-app 的开发流程&#xff0c;包括从创建项目到部署的各个阶段。 1. 创建项目 通过 HB…...

Linux Shell: 使用 Expect 自动化 SCP 和 SSH 连接的 Shell 脚本详解

文章目录 0. 引言2. 解决方案3. 脚本详解脚本1&#xff1a;使用 SSH 和 Expect 自动化登录远端机器脚本说明 脚本2&#xff1a;使用 SCP 和 Expect 自动化文件上传脚本说明 脚本3&#xff1a;使用 SCP 和 Expect 自动化文件下载脚本说明 4. 脚本的使用方法5. 关键技术点5.1. Ex…...

深入分析MySQL事务日志-Undo Log日志

文章目录 InnoDB事务日志-Undo Log日志2.1 Undo Log2.1.1 Undo Log与原子性2.1.2 Undo的存储格式1&#xff09;insert类型Undo Log2&#xff09;delete类型Undo Log3&#xff09;update类型Undo Log 2.1.3 Undo Log的工作原理2.1.4 Undo Log的系统参数2.1.5 Undo Log与Purge线程…...

828华为云征文 | 在Huawei Cloud EulerOS系统中安装Docker的详细步骤与常见问题解决

前言 Docker是一种轻量级的容器技术&#xff0c;广泛用于应用程序的开发、部署和运维。在华为云的欧拉&#xff08;Huawei Cloud EulerOS&#xff09;系统上安装和运行Docker&#xff0c;虽然与CentOS有相似之处&#xff0c;但在具体实现过程中&#xff0c;可能会遇到一些系统…...

什么是数据增强中的插值法?

一、插值法的概念 在数据增强中&#xff0c;插值法是一种重要的技术&#xff0c;它通过数学模型在已知数据点之间估计未知数据点的值。这种方法可以帮助我们在不增加实际数据的情况下&#xff0c;通过生成新的数据点来扩展数据集。插值法基于这样的假设&#xff1a;如果已知的数…...

springboot实战学习(9)(配置mybatis“驼峰命名“和“下划线命名“自动转换)(postman接口测试统一添加请求头)(获取用户详细信息接口)

接着学习。之前的博客的进度&#xff1a;完成用户模块的注册接口的开发以及注册时的参数合法性校验、也基本完成用户模块的登录接口的主逻辑的基础上、JWT令牌"的组成与使用以及完成了"登录认证"&#xff08;生成与验证JWT令牌&#xff09;具体往回看了解的链接…...

之前做了抵押贷款,现在房市不景气,马上贷款要到期了该怎么办?

面对房贷的重压&#xff0c;特别是对于那些正承受高息贷款之苦的现有房产业主而言&#xff0c;探索有效的减负策略显得尤为重要。今天&#xff0c;我们共同探讨几种智慧策略&#xff0c;旨在帮助您巧妙减轻房贷的经济负担。 一、优化贷款结构&#xff1a;低息置换的魔力 当前&a…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...