QT网络通信
九、网络
- 基础概念
1.1 TCP/UDP
TCP/UDP
UDP TCP 协议相同点:都存在于传输层,全双工通信
TCP:全双工通信、面向连接、可靠
TCP(即传输控制协议):是一种面向连接的传输层协议,它能提供高可靠性通信(即数据无误、数据无丢失、数据无失序、数据无重复到达的通信)。
高可靠原因:1.三次握手、四次挥手
2. 序列号和应答机制
3. 超时,错误重传机制
适用场景
适合于对传输质量要求较高的通信
在需要可靠数据传输的场合,通常使用TCP协议
MSN/QQ等即时通讯软件的用户登录账户管理相关的功能通常采用TCP协议
UDP:全双工通信、面向无连接、不可靠
UDP(User Datagram Protocol)用户数据报协议,是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输。
适用场景
发送小尺寸数据(如对DNS服务器进行IP地址查询时)
适合于广播/组播式通信中。
MSN/QQ/Skype等即时通讯软件的点对点文本通讯以及音视频通讯通常采用UDP协议
1.2 IP地址与端口号
IP地址
1. IP地址是Internet中主机的标识,本质: 二进制
IP地址一般分割为 4个八位二进制的数(4字节-32位)
2. Internet中的主机要与别的机器通信必须具有一个IP地址
3. IP地址(长度)为32位(IPv4),128位(IPv6),目前ipv6还未普及,主要学习ipv4
4. 每个数据包都必须携带目的IP地址和源IP地址,路由器依靠此信息为数据包选择路由
5. 表示方法 : 点分十进制
点分十进制表示就是用4组从0~255的数字,来表示一个IP地址。
端口号Port
1. 为了区分一台主机接收到的数据包应该给哪个进程来进行处理,使用端口号来区别
(通过 IP地址 找到哪台主机 通过 port端口号 来找到哪台主机的哪个进程)
2. TCP端口号与UDP端口号独立 (UDP port为8888,TCP port也可为8888 )
3. 端口号一般由IANA (Internet Assigned Numbers Authority) 管理
4. 端口(sin_prot)用2个字节表示 2byte (IP地址占4个字节)
众所周知端口(被占用): 1~1023(1~255之间为众所周知端口,通常由UNIX系统占用)
比如文件传输端口 TFTP 端口号为 69
已登记端口:1024~49151 (----可用来建立与其它主机的会话----)
动态或私有端口:49152~65535 --固定某些服务使用--
自定义的端口号建议使用2000以上,且非豹子号(例如6666/8888等)。
仅以使用2000以上,非豹子号的端口号,本次授课采用8887
2、准备工作
与数据库编程一样,Qt的网络功能需要在.pro项目配置文件中增加network模块。

网络编程主要用到两个类:
- QTcpServer

表示一个基于Tcp的服务器,需要注意的是,此类直接继承了QObject类,不继承QIODevice类,因此不具备任何IO的能力。
- QTcpSocket

表示一个基于TCP的Socket连接,间接继承了QIODevice类,因此使用此类对象进行IO读写。
3、相关函数
// 构造函数,堆内存开辟
QTcpServer::QTcpServer(QObject * parent = 0)
// 开启监听服务,等待客户端发起连接
// 参数1:监听来源(那个网段的IP地址),默认值表示不加任何限制
// 参数2:服务器占用的端口号。默认值为0表示随机选取。8887
bool QTcpServer::listen(const QHostAddress & address = QHostAddress::Any, quint16 port = 0)
// 查看当前是否正在监听
bool QTcpServer::isListening() const
// 关闭监听服务
void QTcpServer::close()
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
// 抢占前台
setWindowFlags(Qt::WindowStaysOnTopHint);
server = new QTcpServer(this); // 开启监听
bool result = server->listen(QHostAddress::Any,8887);
if(!result)
{
ui->textBrowser->append("监听失败");
return;
}
ui->textBrowser->append("监听开启成功,端口号为8887");
}Dialog::~Dialog()
{
// 关闭监听功能
if(server->isListening()) // 判断是否正在监听
{
server->close();
}
delete ui;
} 客户端
// 构造函数,堆区开辟
QTcpSocket::QTcpSocket(QObject * parent = 0)
// 连接到服务器
// 参数1:服务器的IP地址
// 参数2:服务器的端口号
// 参数3:打开模式。默认读写模式
void QAbstractSocket::connectToHost(const QString & hostName,
quint16 port,
OpenMode openMode = ReadWritel)[virtual]
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
setWindowFlags(Qt::WindowStaysOnTopHint); connect(ui->pushButtonConn,SIGNAL(clicked()),
this,SLOT(btnConnClickedSlot()));
connect(ui->pushButtonSend,SIGNAL(clicked()),
this,SLOT(btnSendClickedSlot())); socket = new QTcpSocket(this);
}Dialog::~Dialog()
{
// 如果数据流处于打开状态
if(socket->isOpen())
{
// 如果打开则关闭
socket->close();
}
delete ui;
}void Dialog::btnConnClickedSlot()
{
// 获取用户输入的IP和端口
QString ip = ui->lineEditIp->text();
int port = ui->spinBox->value(); // 建立连接
socket->connectToHost(ip,port);
}void Dialog::btnSendClickedSlot()
{} 我们怎么直到,是否有客户端连接了那?
所有通知类,第一时间想到到的信号槽。
// 每当有新的连接可以用时,就会发出此信号
void QTcpServer::newConnection() [signal]
// 连接成功的信号
void QAbstractSocket::connected()[signal]
// 连接失败的信号
void QAbstractSocket::disconnected()[signal]
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
setWindowFlags(Qt::WindowStaysOnTopHint); connect(ui->pushButtonConn,SIGNAL(clicked()),
this,SLOT(btnConnClickedSlot()));
connect(ui->pushButtonSend,SIGNAL(clicked()),
this,SLOT(btnSendClickedSlot())); socket = new QTcpSocket(this);
connect(socket,SIGNAL(connected()),
this,SLOT(connectedSlot()));
connect(socket,SIGNAL(disconnected()),
this,SLOT(disconnectedSlot()));
}Dialog::~Dialog()
{
// 如果数据流处于打开状态
if(socket->isOpen())
{
// 如果打开则关闭
socket->close();
}
delete ui;
}void Dialog::btnConnClickedSlot()
{
// 获取用户输入的IP和端口
QString ip = ui->lineEditIp->text();
int port = ui->spinBox->value(); // 建立连接
socket->connectToHost(ip,port);
}void Dialog::btnSendClickedSlot()
{}// 连接成功
void Dialog::connectedSlot()
{
// 屏蔽连接按钮
ui->pushButtonConn->setEnabled(false);
ui->pushButtonConn->setText("已连接"); // 释放发送按钮
ui->pushButtonSend->setEnabled(true);
}// 断开连接
void Dialog::disconnectedSlot()
{
// 释放连接按钮
ui->pushButtonConn->setEnabled(true);
ui->pushButtonConn->setText("连接"); // 屏蔽发送按钮
ui->pushButtonSend->setEnabled(false);
} 
// 返回与客户端连接的QTcpSocket对象
QTcpSocket * QTcpServer::nextPendingConnection()[virtual]
// 获取对面(客户端)的IP地址
// 返回值为IP地址封装类
QHostAddress QAbstractSocket::peerAddress() const
// 返回对面的(客户端)端口号
quint16 QAbstractSocket::peerPort() const
// 转换为IP地址字符串,在计算机中会自动增加一个前缀
QString QHostAddress::toString() const
客户端.cpp
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
setWindowFlags(Qt::WindowStaysOnTopHint); connect(ui->pushButtonConn,SIGNAL(clicked()),
this,SLOT(btnConnClickedSlot()));
connect(ui->pushButtonSend,SIGNAL(clicked()),
this,SLOT(btnSendClickedSlot())); socket = new QTcpSocket(this);
connect(socket,SIGNAL(connected()),
this,SLOT(connectedSlot()));
connect(socket,SIGNAL(disconnected()),
this,SLOT(disconnectedSlot()));
}Dialog::~Dialog()
{
// 如果数据流处于打开状态
if(socket->isOpen())
{
// 如果打开则关闭
socket->close();
}
delete ui;
}void Dialog::btnConnClickedSlot()
{
// 获取用户输入的IP和端口
QString ip = ui->lineEditIp->text();
int port = ui->spinBox->value(); // 建立连接
socket->connectToHost(ip,port);
}void Dialog::btnSendClickedSlot()
{}// 连接成功
void Dialog::connectedSlot()
{
// 屏蔽连接按钮
ui->pushButtonConn->setEnabled(false);
ui->pushButtonConn->setText("已连接"); // 释放发送按钮
ui->pushButtonSend->setEnabled(true);
}// 断开连接
void Dialog::disconnectedSlot()
{
// 释放连接按钮
ui->pushButtonConn->setEnabled(true);
ui->pushButtonConn->setText("连接"); // 屏蔽发送按钮
ui->pushButtonSend->setEnabled(false);
} 服务端.cpp
#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
// 抢占前台
setWindowFlags(Qt::WindowStaysOnTopHint);
server = new QTcpServer(this); // 开启监听
bool result = server->listen(QHostAddress::Any,8887);
if(!result)
{
ui->textBrowser->append("监听失败");
return;
}
ui->textBrowser->append("监听开启成功,端口号为8887");
connect(server,SIGNAL(newConnection()),this,
SLOT(newConnectionSlot()));
}Dialog::~Dialog()
{
// 关闭监听功能
if(server->isListening()) // 判断是否正在监听
{
server->close();
}
delete ui;
}void Dialog::newConnectionSlot()
{
// 如果不是第一次连接,就踢掉上一个人
if(socket != NULL)
{
// 踢掉上一个人
socket->close();
} // 保存当前连接对象
socket = server->nextPendingConnection(); // 获取对面的IP地址
QString ip = socket->peerAddress().toString(); // 获取对面的端口号
quint16 port = socket->peerPort(); ip.prepend("新连接来了!").append(":").append(QString::number(port)); ui->textBrowser->append(ip);
} // 构造函数
// 参数事Qt的读写类,可以是QFile,也可以是QTcpSocket........
QTextStream::QTextStream(QIODevice * device)
// 输出字符串内容,支持链式调用
QTextStream & operator<<(const QString & string)
// 有数据可读时发射
void QIODevice::readyRead()[signal]
// 读取最大长度为maxlen个QChar的内容,返回值为读取的字符串
QString QTextStream::read(qint64 maxlen)
// 读取所有字符
QString QTextStream::readAll()
// 一次读取一行文本
// 参数为一行文本的最大字符数
QString QTextStream::readLine(qint64 maxlen = 0)
dialog.cpp 服务端
void Dialog::readyReadSlot()
{
// 创建文本对象
QTextStream input(socket);
// 读取内容
QString text = input.read(128);
ui->textBrowser->append(text);
}
dialog.cpp 客户端
// 发送信息
void Dialog::btnSendClickedSlot()
{
QString text = ui->lineEditSend->text();
if(text == "")
{
QMessageBox::warning(this,"提示","请输入发送的内容");
return;
} // 方法一:QTextStream 文本流
// QTextStream直接使用Unicode编码,适合Qt与Qt之间通信。
// 简化文本的读写操作
QTextStream output(socket);
// 发送数据
output << text;
}
dialog.cpp 服务端
void Dialog::readyReadSlot()
{
// // 创建文本对象
// QTextStream input(socket);
// // 读取内容
// QString text = input.read(128);
// ui->textBrowser->append(text); // 读取所有内容
QByteArray bufer = socket->readAll();
// QByteArray -> QString
QString text(bufer);
// 显示
ui->textBrowser->append(text);
}
dialog.cpp 客户端
void Dialog::btnSendClickedSlot()
{
QString text = ui->lineEditSend->text();
if(text == "")
{
QMessageBox::warning(this,"提示","请输入发送的内容");
return;
} // 方法一:QTextStream 文本流
// QTextStream直接使用Unicode编码,适合Qt与Qt之间通信。
// 简化文本的读写操作
// QTextStream output(socket);
// // 发送数据
// output << text; // 方法二、QByteArray
// 以字节为单位,可以与其他编程语言通信
// 可以操作非文本内容
// QString -> QByteArray
QByteArray buffer = text.toUtf8();
socket->write(buffer);
}
相关文章:
QT网络通信
九、网络 基础概念 1.1 TCP/UDP TCP/UDP UDP TCP 协议相同点:都存在于传输层,全双工通信 TCP:全双工通信、面向连接、可靠 TCP(即传输控制协议):是一种面向连接的传输层协议,它能提供高可靠性通…...
案例分析|山西某光伏发电站轨道巡检机器人解决方案
随着光伏发电技术的不断发展,光伏变电站配电室作为能量转换和输送的关键节点,承担着重要的电力分配和保护功能。然而,传统的人工巡检方式存在诸多问题,如巡检周期长、效率低、安全风险高等,已经无法满足光伏变电站配电…...
Apache POl
介绍 Apache POl是一个处理Miscrosoft Ofice各种文件格式的开源项目。简单来说就是,我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作,一般情况下,POI都是用于操作 Excel 文件。 Apache POl 的应用场景 1.银行网银系统导出交易…...
高防服务器托管应注意什么
选择高防服务器托管主要考虑的因素:1.服务商的服务器大小。2.服务器的防御值大小。3.服务器机房的位置以及机房的资质。 具体内容如下: 1.服务器大小是按照U来定的,U是一种表示服务器外部尺寸的单位(计量单位:高度或厚…...
swagger-ui.html报错404,解决办法
swagger-ui.html报错404,解决办法!现在后端开发项目中,为了节省时间,使用swagger插件,可以方便的快捷生成接口文档。但是如果你在请求前端页面路径比如:http://127.0.0.1:7777/swagger-ui.html。找不到。那是因为你的配…...
golang 函数式编程库samber/mo使用: Future
golang 函数式编程库samber/mo使用: Future 如果您对samber/mo库不了解, 请先阅读第一篇 Option 本节讲述Future的使用,它可以帮助我们处理异步编程问题。 示例 我们先来看看下面代码的示例, 注释解释了每一步的操作。 packa…...
【Spring连载】使用Spring Data访问 MongoDB(十四)----Mongodb特有的查询方法
【Spring连载】使用Spring Data访问 MongoDB(十四)----Mongodb特有的查询方法 一、定义通用查询方法二、MongoDB特有的查询方法2.1 地理空间查询Geo-spatial Queries2.2 基于JSON的查询方法和字段限制2.3 使用SpEL表达式的基于JSON的查询2.4 全文检索查询…...
消息中间件篇之RabbitMQ-消息重复消费
一、导致重复消费的情况 1. 网络抖动。 2. 消费者挂了。 消费者消费消息后,当确认消息还没有发送到MQ时,就发生网络抖动或者消费者宕机。那当消费者恢复后,由于MQ没有收到消息,而且消费者有重试机制,消费者就会再一次消…...
常见设计模式之单例模式
单例模式 单例模式是一种常用的软件设计模式,主要目的是确保一个类在整个应用程序生命周期中只有一个实例,并提供一个全局访问点以获取该实例。 单例模式分为几种不同的实现方式,包括懒汉模式和饿汉模式。每种方式都有其特点和适用场景。例如…...
VL817-Q7 USB3.0 HUB芯片 适用于扩展坞 工控机 显示器
VL817-Q7 USB3.1 GEN1 HUB芯片 VL817-Q7 USB3.1 GEN1 HUB芯片 VIA Lab的VL817是一款现代USB 3.1 Gen 1集线器控制器,具有优化的成本结构和完全符合USB标准3.1 Gen 1规范,包括ecn和2017年1月的合规性测试更新。VL817提供双端口和双端口4端口配置&…...
【Android安全】Windows 环境下载 AOSP 源码
准备环境 安装 git 安装 Python 硬盘剩余容量最好大于 800G 打开 Git Bash,用 git 克隆源代码仓库 git clone https://android.googlesource.com/platform/manifest.git //没有梯子使用清华源 git clone https://aosp.tuna.tsinghua.edu.cn/platform/manifest.git这…...
Vue.js+SpringBoot开发快递管理系统
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 数据中心模块2.2 快递类型模块2.3 快递区域模块2.4 快递货架模块2.5 快递档案模块 三、界面展示3.1 登录注册3.2 快递类型3.3 快递区域3.4 快递货架3.5 快递档案3.6 系统基础模块 四、免责说明 一、摘要 1.1 项目介绍 …...
Linux/Spectra
Enumeration nmap 第一次扫描发现系统对外开放了22,80和3306端口,端口详细信息如下 22端口运行着ssh,80端口还是http,不过不同的是打开了mysql的3306端口 TCP/80 进入首页,点击链接时,提示域名不能解析&…...
C 嵌入式系统设计模式 08:硬件代理模式
本书的原著为:《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》,讲解的是嵌入式系统设计模式,是一本不可多得的好书。 本系列描述我对书中内容的理解。本文章描述访问硬件的设计模式之一&…...
【k8s配置与存储--持久化存储(PV、PVC、存储类)】
1、PV与PVC 介绍 持久卷(PersistentVolume,PV) 是集群中的一块存储,可以由管理员事先制备, 或者使用存储类(Storage Class)来动态制备。 持久卷是集群资源,就像节点也是集群资源一样…...
【Vite】解决Vite http proxy error: Error: connect ECONNREFUSED
今天写bug,发现了这个问题 我经过我一晚上的搜索努力,在github上找到了解决办法,不得不说,交友网站还是很好用的。 参考 这一行是关键代码。 因为我连的是本地后台服务,所以最后配置成这样 server: {open: true,pro…...
FPGA领域顶级学术会议
FPGA领域顶级学术会议主要有FPGA,FCCM,FPL和FPT。 1 FPGA 会议全名是: ACM/SIGDA International Symposium on Field-Programmable Gate Arrays 网站是:https://dl.acm.org/conference/fpga FPGA常年在美国举办,每年2月,偏FPGA基础研究; 该会议的论文免费下载。这个比…...
罗技鼠标滚轮模式介绍 | 鼠标滚轮异响 - 解决方案
滚轮模式介绍 针对罗技的滚轮模式进行介绍: 普通滚轮:滚动时有明显段落感,无法快速滚动。 智能滚轮:滚动力量较弱时,与普通滚轮无异;滚动力量大时,鼠标会自动减小滚轮阻尼,从而使滚…...
Scrapy与分布式开发(2.2):正则表达式
使用Python的re模块进行正则表达式操作详细讲解 一、引言 正则表达式是一种强大的文本处理工具,它使用特定的模式来搜索、匹配和替换文本。Python的re模块(正则表达式模块)提供了正则表达式匹配操作的所有功能。下面我们将详细讲解如何使用re模块进行正则表达式的操作。 …...
今年“全国爱耳日”主题确定!立聪堂助听器组织社区义诊
2024年3月3日是第二十五个“全国爱耳日”。 今年的活动主题定为“科技助听,共享美好生活”,旨在倡导全社会关注听力健康,并鼓励听力受损人群利用科技手段实现早期康复。 为响应这一主题,知名助听器验配连锁机构立聪堂迅速行动起…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...
Python常用模块:time、os、shutil与flask初探
一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...
2025-05-08-deepseek本地化部署
title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek:小白也能轻松搞定! 如何给本地部署的 DeepSeek 投喂数据,让他更懂你 [实验目的]:理解系统架构与原…...
