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

QT:一个TCP客户端自动连接的测试模型

版本 1:没有取消按钮

 测试效果:

缺陷:

无法手动停止

测试代码

CMakeLists.txt

cmake_minimum_required(VERSION 3.19)
project(AutoConnect LANGUAGES CXX)find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets Network)qt_standard_project_setup()qt_add_executable(AutoConnectWIN32 MACOSX_BUNDLEmain.cppwidget.hwidget.ui
)target_link_libraries(AutoConnectPRIVATEQt::CoreQt::WidgetsQt6::Network
)include(GNUInstallDirs)install(TARGETS AutoConnectBUNDLE  DESTINATION .RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)qt_generate_deploy_app_script(TARGET AutoConnectOUTPUT_SCRIPT deploy_scriptNO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})

main.cpp 

#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpSocket>
#include <QProgressDialog>
#include <QPushButton>
#include <QLabel>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QTextBrowser>
#include <QMouseEvent>
#include <QLineEdit>
#include <QDebug>
#include <QMetaObject>
#include <QProgressBar>
#include <QTimer>class MyTextBrowser:public QTextBrowser
{
public:MyTextBrowser(QWidget *parent = nullptr):QTextBrowser(parent){}// QWidget interface
protected:virtual void mouseDoubleClickEvent(QMouseEvent *event) override{if(event->button() == Qt::LeftButton){this->clear();}}
};class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr): QWidget(parent){QVBoxLayout *root = new QVBoxLayout(this);QHBoxLayout *iplayout = new QHBoxLayout;QPushButton *button_connect = new QPushButton("connect",this);button_connect->setObjectName("connect");QLabel *ip_label = new QLabel("ip",this);QLabel *port_label = new QLabel("port",this);iplayout->addWidget(ip_label);iplayout->addWidget(ip_LineEdit);iplayout->addWidget(port_label);iplayout->addWidget(port_LineEdit);iplayout->addWidget(button_connect);iplayout->addStretch();root->addLayout(iplayout);root->addWidget(console,1);//设置默认的测试网络参数ip_LineEdit->setText("127.0.0.1");port_LineEdit->setText("6600");client->setObjectName("client");QMetaObject::connectSlotsByName(this);}~Widget(){}
public slots:void auto_connect(){if(client->state() == QAbstractSocket::ConnectedState){client->disconnectFromHost();client->waitForDisconnected();}//client->waitForConnected();std::shared_ptr<QProgressDialog> dialog(new QProgressDialog(this));dialog->setLabelText("");QProgressBar *bar = new QProgressBar(dialog.get());bar->setTextVisible(false);dialog->setBar(bar);dialog->setLabelText("connecting ... ");dialog->setRange(0,0);dialog->setCancelButton(nullptr);dialog->setWindowFlag(Qt::FramelessWindowHint);QMetaObject::Connection conn_accept= connect(client,&QTcpSocket::connected,dialog.get(),&QProgressDialog::accept);QMetaObject::Connection conn_rejected= connect(client,&QTcpSocket::stateChanged,dialog.get(),[this,dialog](){if(this->client->state() ==QAbstractSocket::UnconnectedState){dialog->reject();}});bool rtn = false;if(conn_accept&&conn_accept){QHostAddress ip(ip_LineEdit->text());int port = port_LineEdit->text().toInt();show_msg(QString("connect %1:%2 ...").arg(ip.toString()).arg(port));client->connectToHost(ip,port);rtn = dialog->exec();qDebug() << "rtn = " << rtn;if(rtn == true){show_msg(QString("connect %1:%2 success").arg(ip.toString()).arg(port));}else{show_msg(QString("connect %1:%2 fail").arg(ip.toString()).arg(port));}}else{qDebug() << "error";}if(conn_accept){QObject::disconnect(conn_accept);}if(conn_rejected){QObject::disconnect(conn_rejected);}if(!rtn){QTimer::singleShot(10, this, &Widget::auto_connect);}}void on_connect_clicked(){qDebug() << "clicked";auto_connect();}void on_client_connected(){QTcpSocket *c = (QTcpSocket *)sender();qDebug() << c->peerAddress() << "-" << c->peerName() << "-" << c->peerPort();show_msg(QString("connect %1:%2 ok").arg(c->peerAddress().toString()).arg(c->peerPort()));}void on_client_disconnected(){qDebug() << __func__<<__LINE__;show_msg(QString("disconnected"));QTimer::singleShot(10, this, &Widget::auto_connect);}void on_client_errorOccurred(QAbstractSocket::SocketError socketError){qDebug() << __func__<<__LINE__ << "socketError:" << socketError;}void on_client_hostFound(){qDebug() << __func__<<__LINE__;}// void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)void on_client_stateChanged(QAbstractSocket::SocketState socketState){qDebug() << __func__<<__LINE__<< "socketState:"<<socketState;}void show_msg(QString msg){console->append(msg);}void on_client_aboutToClose(){qDebug() << __func__<<__LINE__;}// void bytesWritten(qint64 bytes)// void channelBytesWritten(int channel, qint64 bytes)void on_client_channelReadyRead(int channel){qDebug() << __func__<<__LINE__<< "channel:"<<channel;}void on_client_readChannelFinished(){qDebug() << __func__<<__LINE__;}void on_client_readyRead(){qDebug() << __func__<<__LINE__;}public:QTcpSocket *client = new QTcpSocket(this);MyTextBrowser *console = new MyTextBrowser;QLineEdit *ip_LineEdit = new QLineEdit;QLineEdit *port_LineEdit = new QLineEdit;private:
};
#endif // WIDGET_H

版本 2:有取消按钮

 测试效果:

点击canel按钮后,就不会自动重连了:

 

测试代码

CMakeLists.txt

cmake_minimum_required(VERSION 3.19)
project(AutoConnect LANGUAGES CXX)find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets Network)qt_standard_project_setup()qt_add_executable(AutoConnectWIN32 MACOSX_BUNDLEmain.cppwidget.hwidget.ui
)target_link_libraries(AutoConnectPRIVATEQt::CoreQt::WidgetsQt6::Network
)include(GNUInstallDirs)install(TARGETS AutoConnectBUNDLE  DESTINATION .RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)qt_generate_deploy_app_script(TARGET AutoConnectOUTPUT_SCRIPT deploy_scriptNO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})

main.cpp 

#include "widget.h"#include <QApplication>
int MyPushButton::count = 0;
int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QApplication>
#include <QWidget>
#include <QTcpSocket>
#include <QProgressDialog>
#include <QPushButton>
#include <QLabel>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QTextBrowser>
#include <QMouseEvent>
#include <QLineEdit>
#include <QDebug>
#include <QMetaObject>
#include <QProgressBar>
#include <QTimer>class MyTextBrowser:public QTextBrowser
{
public:MyTextBrowser(QWidget *parent = nullptr):QTextBrowser(parent){}// QWidget interface
protected:virtual void mouseDoubleClickEvent(QMouseEvent *event) override{if(event->button() == Qt::LeftButton){this->clear();}}
};
class MyPushButton:public QPushButton{Q_OBJECT
public:MyPushButton(QWidget *parent = nullptr):MyPushButton("",parent){}MyPushButton(const QString &text, QWidget *parent = nullptr):QPushButton(text,parent){MyPushButton::count++;qDebug() << __func__ << __LINE__ << " create MyPushButton:count = "  << count;}~MyPushButton(){MyPushButton::count--;qDebug() << __func__ << __LINE__ << " delete MyPushButton:count = " << count;}
public:static int count;
signals:void user_click();// QWidget interface
protected:virtual void mousePressEvent(QMouseEvent *event) override{if(event->button() == Qt::LeftButton){qDebug() << __func__ << __LINE__ << "user click";emit user_click();}}
};class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr): QWidget(parent){QVBoxLayout *root = new QVBoxLayout(this);QHBoxLayout *iplayout = new QHBoxLayout;QPushButton *button_connect = new QPushButton("connect",this);button_connect->setObjectName("connect");QLabel *ip_label = new QLabel("ip",this);QLabel *port_label = new QLabel("port",this);iplayout->addWidget(ip_label);iplayout->addWidget(ip_LineEdit);iplayout->addWidget(port_label);iplayout->addWidget(port_LineEdit);//iplayout->addWidget(button_connect);button_connect->setVisible(false);iplayout->addStretch();root->addLayout(iplayout);root->addWidget(console,1);//设置默认的测试网络参数ip_LineEdit->setText("127.0.0.1");port_LineEdit->setText("6600");client->setObjectName("client");QMetaObject::connectSlotsByName(this);QTimer::singleShot(10, this, &Widget::auto_connect);// std::shared_ptr<QProgressDialog> dialog(new QProgressDialog(this));// dialog->setCancelButton(new MyPushButton("hello",this));// qDebug() << "wait ...";// dialog.reset();// qDebug() << "byebye ...";}~Widget(){}
public slots:void auto_connect(){if(client->state() == QAbstractSocket::ConnectedState){client->disconnectFromHost();client->waitForDisconnected();}//client->waitForConnected();std::shared_ptr<QProgressDialog> dialog(new QProgressDialog(this));dialog->setLabelText("");QProgressBar *bar = new QProgressBar(dialog.get());bar->setTextVisible(false);dialog->setBar(bar);dialog->setLabelText("connecting ... ");dialog->setRange(0,0);MyPushButton *cancel_button = new MyPushButton("cancel",dialog.get());dialog->setCancelButton(cancel_button);dialog->setWindowFlag(Qt::FramelessWindowHint);QMetaObject::Connection conn_accept= connect(client,&QTcpSocket::connected,dialog.get(),&QProgressDialog::accept);QMetaObject::Connection conn_rejected= connect(client,&QTcpSocket::stateChanged,dialog.get(),[this,dialog](){if(this->client->state() ==QAbstractSocket::UnconnectedState){qDebug() << "connect error";dialog->reject();}});QMetaObject::Connection conn_cancel= connect(cancel_button,&MyPushButton::user_click,dialog.get(),[this,dialog](){qDebug() << "connect error";dialog->reject();this->m_user_cancel = true;show_msg("user cancel reconnect");});bool rtn = false;if(conn_accept&&conn_accept&&conn_cancel){QHostAddress ip(ip_LineEdit->text());int port = port_LineEdit->text().toInt();show_msg(QString("connect %1:%2 ...").arg(ip.toString()).arg(port));client->connectToHost(ip,port);rtn = dialog->exec();qDebug() << "rtn = " << rtn;if(rtn == true){show_msg(QString("connect %1:%2 success").arg(ip.toString()).arg(port));}else{show_msg(QString("connect %1:%2 fail").arg(ip.toString()).arg(port));}}else{qDebug() << "error";}if(conn_accept){QObject::disconnect(conn_accept);}if(conn_rejected){QObject::disconnect(conn_rejected);}if(conn_rejected){QObject::disconnect(conn_rejected);}if(conn_cancel){QObject::disconnect(conn_cancel);}if(!rtn){if(this->m_user_cancel == false){QTimer::singleShot(10, this, &Widget::auto_connect);}}}void on_connect_clicked(){qDebug() << "clicked";auto_connect();}void on_client_connected(){QTcpSocket *c = (QTcpSocket *)sender();qDebug() << c->peerAddress() << "-" << c->peerName() << "-" << c->peerPort();show_msg(QString("connect %1:%2 ok").arg(c->peerAddress().toString()).arg(c->peerPort()));}void on_client_disconnected(){qDebug() << __func__<<__LINE__;show_msg(QString("disconnected"));QTimer::singleShot(10, this, &Widget::auto_connect);}void on_client_errorOccurred(QAbstractSocket::SocketError socketError){qDebug() << __func__<<__LINE__ << "socketError:" << socketError;}void on_client_hostFound(){qDebug() << __func__<<__LINE__;}// void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)void on_client_stateChanged(QAbstractSocket::SocketState socketState){qDebug() << __func__<<__LINE__<< "socketState:"<<socketState;}void show_msg(QString msg){console->append(msg);}void on_client_aboutToClose(){qDebug() << __func__<<__LINE__;}// void bytesWritten(qint64 bytes)// void channelBytesWritten(int channel, qint64 bytes)void on_client_channelReadyRead(int channel){qDebug() << __func__<<__LINE__<< "channel:"<<channel;}void on_client_readChannelFinished(){qDebug() << __func__<<__LINE__;}void on_client_readyRead(){qDebug() << __func__<<__LINE__;}public:bool m_user_cancel = false;QTcpSocket *client = new QTcpSocket(this);MyTextBrowser *console = new MyTextBrowser;QLineEdit *ip_LineEdit = new QLineEdit;QLineEdit *port_LineEdit = new QLineEdit;private:
};
#endif // WIDGET_H

小结

相关文章:

QT:一个TCP客户端自动连接的测试模型

版本 1:没有取消按钮 测试效果&#xff1a; 缺陷&#xff1a; 无法手动停止 测试代码 CMakeLists.txt cmake_minimum_required(VERSION 3.19) project(AutoConnect LANGUAGES CXX)find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets Network)qt_standard_project_setup(…...

关于启动vue项目,出现:Error [ERR_MODULE_NOT_FOUND]: Cannot find module ‘xxx‘此类错误

目录 一、问题报错 二、原因分析 三、解决方法 一、问题报错 node环境变量配置有问题&#xff1a; (base) xxxM73H-15:~/VueProject/pproject-vue$ npm run dev /usr/bin/env: “node”: 没有那个文件或目录vue项目启动有问题&#xff1a; (base) xxx:~/VueProject/pproj…...

电路元件与电路基本定理

电流、电压和电功率 电流 1 定义&#xff1a; 带电质点的有序运动形成电流 。 单位时间内通过导体横截面的电量定义为电流强度&#xff0c; 简称电流&#xff0c;用符号 i 表示&#xff0c;其数学表达式为&#xff1a;&#xff08;i单位&#xff1a;安培&#xff08;A&#x…...

指针之矢:C 语言内存幽境的精准飞梭

一、内存和编码 指针理解的2个要点&#xff1a; 指针是内存中一个最小单元的编号&#xff0c;也就是地址平时口语中说的指针&#xff0c;通常指的是指针变量&#xff0c;是用来存放内存地址的变量 总结&#xff1a;指针就是地址&#xff0c;口语中说的指针通常指的是指针变量。…...

uniapp下载打开实现方案,支持安卓ios和h5,下载文件到指定目录,安卓文件管理内可查看到

uniapp下载&打开实现方案&#xff0c;支持安卓ios和h5 Android&#xff1a; 1、申请本地存储读写权限 2、创建文件夹&#xff08;文件夹不存在即创建&#xff09; 3、下载文件 ios&#xff1a; 1、下载文件 2、保存到本地&#xff0c;需要打开文件点击储存 使用方法&…...

免费干净!付费软件的平替款!

今天给大家介绍一个非常好用的电脑录屏软件&#xff0c;完全没有广告界面&#xff0c;非常的干净简洁。 电脑录屏 无广告的录屏软件 这个软件不需要安装&#xff0c;打开就能看到界面直接使用了。 软件可以全屏录制&#xff0c;也可以自定义尺寸进行录制。 录制的声音选择也非…...

软路由系统 iStoreOS 中部署 Minecraft 服务器

商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。协议(License): 知识共享署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)作者(Author): lhDream链接(URL): https://blog.luhua.site/archives/1734968846131 软路由系统 iStoreOS 中部署 Minecraft…...

第 29 章 - ES 源码篇 - 网络 IO 模型及其实现概述

前言 本文介绍了 ES 使用的网络模型&#xff0c;并介绍 transport&#xff0c;http 接收、响应请求的代码入口。 网络 IO 模型 Node 在初始化的时候&#xff0c;会创建网络模块。网络模块会加载 Netty4Plugin plugin。 而后由 Netty4Plugin 创建对应的 transports&#xff0…...

细说STM32F407单片机IIC总线基础知识

目录 一、 I2C总线结构 1、I2C总线的特点 2、I2C总线通信协议 3、 STM32F407的I2C接口 二、 I2C的HAL驱动程序 1、 I2C接口的初始化 2、阻塞式数据传输 &#xff08;1&#xff09;函数HAL_I2C_IsDeviceReady() &#xff08;2&#xff09;主设备发送和接收数据 &#…...

从头开始学MyBatis—04缓存、逆向工程、分页插件

介绍了MyBatis的缓存、逆向工程和分页插件的使用 目录 1.Mybatis的缓存 1.1MyBatis的一级缓存 1.2MyBatis的二级缓存 1.3二级缓存的相关配置 1.4MyBatis缓存查询的顺序 1.5整合第三方缓存EHCache 1.5.1添加依赖 1.5.2各jar包功能 1.5.3创建EHCache的配置文件ehcache.x…...

Artec Space Spider助力剑桥研究团队解码古代社会合作【沪敖3D】

挑战&#xff1a;考古学家需要一种安全的方法来呈现新出土的陶瓷容器&#xff0c;对比文物形状。 解决方案&#xff1a;Artec Space Spider, Artec Studio 效果&#xff1a;本项目是REVERSEACTION项目的一部分&#xff0c;旨在研究无国家社会中复杂的古代技术。研究团队在考古地…...

《探索PyTorch计算机视觉:原理、应用与实践》

《探索PyTorch计算机视觉&#xff1a;原理、应用与实践》 一、PyTorch 与计算机视觉的奇妙相遇二、核心概念解析&#xff08;一&#xff09;张量&#xff1a;计算机视觉的数据基石&#xff08;二&#xff09;神经网络&#xff1a;视觉任务的智慧大脑&#xff08;三&#xff09;…...

【C#设计模式(21)——状态模式(State Pattern)】

前言 状态模式:在对象内部发生改变时改变其行为&#xff0c;使得对象在不同的状态下具有不同的行为表现。 代码 #region 状态模式-类/// 抽象 交通灯状态public abstract class TrafficLightState{public abstract void Display();}//红灯public class RedLight : TrafficLight…...

nvm日常使用中常用命令总结

日常开发vue项目中&#xff0c;不同的项目 我们可能需要安装不同的node版本&#xff0c;但是为了方便切换node&#xff0c;我们一般会安装一个名称为nvm的工具&#xff0c;这里总结一下&#xff0c;nvm常用的命令&#xff1a; 1、为了查看可用的 Node.js 版本&#xff0c;你可…...

【数据仓库】SparkSQL数仓实践

文章目录 集成hive metastoreSQL测试spark-sql 语法SQL执行流程两种数仓架构的选择hive on spark数仓配置经验 spark-sql没有元数据管理功能&#xff0c;只有sql 到RDD的解释翻译功能&#xff0c;所以需要和hive的metastore服务集成在一起使用。 集成hive metastore 在spark安…...

PessimisticLock

想象你和你的朋友都想去图书馆借同一本非常受欢迎的小说。为了确保你们中的一位能够成功借到这本书&#xff0c;图书馆采用了悲观锁机制来管理借阅过程。 悲观锁的方式 查看书籍状态&#xff1a;当你到达图书馆并决定要借这本小说时&#xff0c;你先告诉图书管理员你想借这本…...

【Maven】属性管理

1. 属性 问题导入 定义属性有什么好处&#xff1f; 1.1 属性配置与使用 ①&#xff1a;定义属性 <!--定义自定义属性--> <properties><spring.version>5.2.10.RELEASE</spring.version><junit.version>4.12</junit.version> </prop…...

微信小程序性能优化、分包

性能优化是任何应用开发中的重要组成部分&#xff0c;尤其是在移动环境中。对于微信小程序而言&#xff0c;随着用户量的增加和应用功能的丰富&#xff0c;性能优化显得尤为关键。良好的性能不仅提升用户体验&#xff0c;还能增加用户留存率和应用的使用频率。我们将探讨如何在…...

TDengine 新功能 VARBINARY 数据类型

1. 背景 VARBINARY 数据类型用于存储二进制数据&#xff0c;与 MySQL 中的 VARBINARY 数据类型功能相同&#xff0c;VARBINARY 数据类型长度可变&#xff0c;在创建表时指定最大字节长度&#xff0c;使用进按需分配存储&#xff0c;但不能超过建表时指定的最大值。 2. 功能说明…...

【Maven】工程依赖下载失败错误解决

在使用 Maven 构建项目时&#xff0c;可能会发生依赖项下载错误的情况&#xff0c;主要原因有以下几种&#xff1a; 下载依赖时出现网络故障或仓库服务器宕机等原因&#xff0c;导致无法连接至 Maven 仓库&#xff0c;从而无法下载依赖。 依赖项的版本号或配置文件中的版本号错…...

给客户发固件,别再傻傻传源码了!手把手教你用ESP32 Download Tool烧录PlatformIO生成的bin文件

专业级ESP32固件交付方案&#xff1a;从PlatformIO编译到客户安全烧录全流程 当我们需要将开发完成的ESP32固件交付给客户时&#xff0c;直接发送源代码往往不是最佳选择。这不仅涉及知识产权保护问题&#xff0c;还可能因为客户缺乏开发环境而导致沟通成本激增。本文将详细介绍…...

基于LangChain的RAG与Agent智能体开发 - 向量存储与向量检索,以及RAG增强检索实现

大家好&#xff0c;我是小锋老师&#xff0c;最近更新《2027版 基于LangChain的RAG与Agent智能体 开发视频教程》专辑&#xff0c;感谢大家支持。本课程主要介绍和讲解RAG&#xff0c;LangChain简介&#xff0c;接入通义千万大模型 &#xff0c;Ollama简介以及安装和使…...

百考通:AI全流程智能化赋能期刊论文写作,让学术创作更高效

在学术研究领域&#xff0c;期刊论文的撰写是成果输出的关键环节&#xff0c;却也让众多科研工作者与学生倍感压力&#xff1a;选题迷茫、逻辑梳理困难、格式规范复杂、内容提炼耗时&#xff0c;严重拖慢了学术成果的发表节奏。百考通&#xff08;https://www.baikaotongai.com…...

PaddleOCR Docker镜像实战:从Java调用到表格识别,一个容器搞定OCR全流程

PaddleOCR Docker镜像实战&#xff1a;从Java调用到表格识别全流程指南 在数字化转型浪潮中&#xff0c;OCR&#xff08;光学字符识别&#xff09;技术已成为企业处理纸质文档、票据和表格数据的关键工具。PaddleOCR作为百度开源的OCR解决方案&#xff0c;凭借其出色的中文识别…...

八位行波进位加法器设计全攻略:从理论到Quartus II实现

八位行波进位加法器设计全攻略&#xff1a;从理论到Quartus II实现 在数字电路设计中&#xff0c;加法器是最基础也是最重要的运算单元之一。无论是简单的计算器还是复杂的CPU&#xff0c;都离不开高效可靠的加法器设计。八位行波进位加法器作为入门级但实用性极强的设计案例&a…...

Windows 11性能优化指南:让系统重获新生的实用工具

Windows 11性能优化指南&#xff1a;让系统重获新生的实用工具 【免费下载链接】Win11Debloat 一个简单的PowerShell脚本&#xff0c;用于从Windows中移除预装的无用软件&#xff0c;禁用遥测&#xff0c;从Windows搜索中移除Bing&#xff0c;以及执行各种其他更改以简化和改善…...

别再死记硬背了!用Synopsys DC和ICC搞懂数字IC设计全流程(附避坑清单)

数字IC设计实战&#xff1a;从Synopsys工具链透视高效学习路径 刚接触数字IC设计的工程师常陷入一个怪圈&#xff1a;背了大量DC和ICC命令&#xff0c;面对真实项目却无从下手。这就像背熟了菜谱却做不出佳肴——问题不在于记忆容量&#xff0c;而在于理解烹饪原理和规避操作误…...

【跟韩工学Ubuntu第9课】第9章 系统备份、恢复与迁移-005篇

文章目录 第9章 系统备份、恢复与迁移 Ubuntu Server 生产级系统管理(企业级完整版) 9.1 备份策略基础(企业级理论精讲) 9.1.1 企业备份核心价值观 9.1.2 企业级3-2-1备份黄金法则 9.1.3 全量备份(Full Backup) 定义 企业级优点 企业级缺点 企业适用场景 9.1.4 增量备份(…...

3倍效能革命:ComfyUI-TeaCache智能缓存技术重构AI创作流程

3倍效能革命&#xff1a;ComfyUI-TeaCache智能缓存技术重构AI创作流程 【免费下载链接】ComfyUI-TeaCache 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-TeaCache 在AI创作领域&#xff0c;每一秒的等待都可能错失灵感迸发的瞬间。ComfyUI-TeaCache作为一款基…...

如何永久保存微信聊天记录?WeChatMsg免费工具终极指南

如何永久保存微信聊天记录&#xff1f;WeChatMsg免费工具终极指南 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeCha…...