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

QT网络通信

九、网络

  1. 基础概念

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 协议相同点&#xff1a;都存在于传输层&#xff0c;全双工通信 TCP&#xff1a;全双工通信、面向连接、可靠 TCP&#xff08;即传输控制协议&#xff09;&#xff1a;是一种面向连接的传输层协议&#xff0c;它能提供高可靠性通…...

案例分析|山西某光伏发电站轨道巡检机器人解决方案

随着光伏发电技术的不断发展&#xff0c;光伏变电站配电室作为能量转换和输送的关键节点&#xff0c;承担着重要的电力分配和保护功能。然而&#xff0c;传统的人工巡检方式存在诸多问题&#xff0c;如巡检周期长、效率低、安全风险高等&#xff0c;已经无法满足光伏变电站配电…...

Apache POl

介绍 Apache POl是一个处理Miscrosoft Ofice各种文件格式的开源项目。简单来说就是&#xff0c;我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作,一般情况下&#xff0c;POI都是用于操作 Excel 文件。 Apache POl 的应用场景 1.银行网银系统导出交易…...

高防服务器托管应注意什么

选择高防服务器托管主要考虑的因素&#xff1a;1.服务商的服务器大小。2.服务器的防御值大小。3.服务器机房的位置以及机房的资质。 具体内容如下&#xff1a; 1&#xff0e;服务器大小是按照U来定的&#xff0c;U是一种表示服务器外部尺寸的单位(计量单位&#xff1a;高度或厚…...

swagger-ui.html报错404,解决办法

swagger-ui.html报错404,解决办法&#xff01;现在后端开发项目中&#xff0c;为了节省时间&#xff0c;使用swagger插件&#xff0c;可以方便的快捷生成接口文档。但是如果你在请求前端页面路径比如&#xff1a;http://127.0.0.1:7777/swagger-ui.html。找不到。那是因为你的配…...

golang 函数式编程库samber/mo使用: Future

golang 函数式编程库samber/mo使用&#xff1a; Future 如果您对samber/mo库不了解&#xff0c; 请先阅读第一篇 Option 本节讲述Future的使用&#xff0c;它可以帮助我们处理异步编程问题。 示例 我们先来看看下面代码的示例&#xff0c; 注释解释了每一步的操作。 packa…...

【Spring连载】使用Spring Data访问 MongoDB(十四)----Mongodb特有的查询方法

【Spring连载】使用Spring Data访问 MongoDB&#xff08;十四&#xff09;----Mongodb特有的查询方法 一、定义通用查询方法二、MongoDB特有的查询方法2.1 地理空间查询Geo-spatial Queries2.2 基于JSON的查询方法和字段限制2.3 使用SpEL表达式的基于JSON的查询2.4 全文检索查询…...

消息中间件篇之RabbitMQ-消息重复消费

一、导致重复消费的情况 1. 网络抖动。 2. 消费者挂了。 消费者消费消息后&#xff0c;当确认消息还没有发送到MQ时&#xff0c;就发生网络抖动或者消费者宕机。那当消费者恢复后&#xff0c;由于MQ没有收到消息&#xff0c;而且消费者有重试机制&#xff0c;消费者就会再一次消…...

常见设计模式之单例模式

单例模式 单例模式是一种常用的软件设计模式&#xff0c;主要目的是确保一个类在整个应用程序生命周期中只有一个实例&#xff0c;并提供一个全局访问点以获取该实例。 单例模式分为几种不同的实现方式&#xff0c;包括懒汉模式和饿汉模式。每种方式都有其特点和适用场景。例如…...

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集线器控制器&#xff0c;具有优化的成本结构和完全符合USB标准3.1 Gen 1规范&#xff0c;包括ecn和2017年1月的合规性测试更新。VL817提供双端口和双端口4端口配置&…...

【Android安全】Windows 环境下载 AOSP 源码

准备环境 安装 git 安装 Python 硬盘剩余容量最好大于 800G 打开 Git Bash&#xff0c;用 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&#xff0c;80和3306端口&#xff0c;端口详细信息如下 22端口运行着ssh&#xff0c;80端口还是http&#xff0c;不过不同的是打开了mysql的3306端口 TCP/80 进入首页&#xff0c;点击链接时&#xff0c;提示域名不能解析&…...

C 嵌入式系统设计模式 08:硬件代理模式

本书的原著为&#xff1a;《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》&#xff0c;讲解的是嵌入式系统设计模式&#xff0c;是一本不可多得的好书。 本系列描述我对书中内容的理解。本文章描述访问硬件的设计模式之一&…...

【k8s配置与存储--持久化存储(PV、PVC、存储类)】

1、PV与PVC 介绍 持久卷&#xff08;PersistentVolume&#xff0c;PV&#xff09; 是集群中的一块存储&#xff0c;可以由管理员事先制备&#xff0c; 或者使用存储类&#xff08;Storage Class&#xff09;来动态制备。 持久卷是集群资源&#xff0c;就像节点也是集群资源一样…...

【Vite】解决Vite http proxy error: Error: connect ECONNREFUSED

今天写bug&#xff0c;发现了这个问题 我经过我一晚上的搜索努力&#xff0c;在github上找到了解决办法&#xff0c;不得不说&#xff0c;交友网站还是很好用的。 参考 这一行是关键代码。 因为我连的是本地后台服务&#xff0c;所以最后配置成这样 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基础研究; 该会议的论文免费下载。这个比…...

罗技鼠标滚轮模式介绍 | 鼠标滚轮异响 - 解决方案

滚轮模式介绍 针对罗技的滚轮模式进行介绍&#xff1a; 普通滚轮&#xff1a;滚动时有明显段落感&#xff0c;无法快速滚动。 智能滚轮&#xff1a;滚动力量较弱时&#xff0c;与普通滚轮无异&#xff1b;滚动力量大时&#xff0c;鼠标会自动减小滚轮阻尼&#xff0c;从而使滚…...

Scrapy与分布式开发(2.2):正则表达式

使用Python的re模块进行正则表达式操作详细讲解 一、引言 正则表达式是一种强大的文本处理工具,它使用特定的模式来搜索、匹配和替换文本。Python的re模块(正则表达式模块)提供了正则表达式匹配操作的所有功能。下面我们将详细讲解如何使用re模块进行正则表达式的操作。 …...

今年“全国爱耳日”主题确定!立聪堂助听器组织社区义诊

2024年3月3日是第二十五个“全国爱耳日”。 今年的活动主题定为“科技助听&#xff0c;共享美好生活”&#xff0c;旨在倡导全社会关注听力健康&#xff0c;并鼓励听力受损人群利用科技手段实现早期康复。 为响应这一主题&#xff0c;知名助听器验配连锁机构立聪堂迅速行动起…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; 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毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 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&#xff1a;小白也能轻松搞定&#xff01; 如何给本地部署的 DeepSeek 投喂数据&#xff0c;让他更懂你 [实验目的]&#xff1a;理解系统架构与原…...