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:没有取消按钮 测试效果: 缺陷: 无法手动停止 测试代码 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环境变量配置有问题: (base) xxxM73H-15:~/VueProject/pproject-vue$ npm run dev /usr/bin/env: “node”: 没有那个文件或目录vue项目启动有问题: (base) xxx:~/VueProject/pproj…...
电路元件与电路基本定理
电流、电压和电功率 电流 1 定义: 带电质点的有序运动形成电流 。 单位时间内通过导体横截面的电量定义为电流强度, 简称电流,用符号 i 表示,其数学表达式为:(i单位:安培(A&#x…...
指针之矢:C 语言内存幽境的精准飞梭
一、内存和编码 指针理解的2个要点: 指针是内存中一个最小单元的编号,也就是地址平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量 总结:指针就是地址,口语中说的指针通常指的是指针变量。…...
uniapp下载打开实现方案,支持安卓ios和h5,下载文件到指定目录,安卓文件管理内可查看到
uniapp下载&打开实现方案,支持安卓ios和h5 Android: 1、申请本地存储读写权限 2、创建文件夹(文件夹不存在即创建) 3、下载文件 ios: 1、下载文件 2、保存到本地,需要打开文件点击储存 使用方法&…...
免费干净!付费软件的平替款!
今天给大家介绍一个非常好用的电脑录屏软件,完全没有广告界面,非常的干净简洁。 电脑录屏 无广告的录屏软件 这个软件不需要安装,打开就能看到界面直接使用了。 软件可以全屏录制,也可以自定义尺寸进行录制。 录制的声音选择也非…...
软路由系统 iStoreOS 中部署 Minecraft 服务器
商业转载请联系作者获得授权,非商业转载请注明出处。协议(License): 知识共享署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)作者(Author): lhDream链接(URL): https://blog.luhua.site/archives/1734968846131 软路由系统 iStoreOS 中部署 Minecraft…...
第 29 章 - ES 源码篇 - 网络 IO 模型及其实现概述
前言 本文介绍了 ES 使用的网络模型,并介绍 transport,http 接收、响应请求的代码入口。 网络 IO 模型 Node 在初始化的时候,会创建网络模块。网络模块会加载 Netty4Plugin plugin。 而后由 Netty4Plugin 创建对应的 transports࿰…...
细说STM32F407单片机IIC总线基础知识
目录 一、 I2C总线结构 1、I2C总线的特点 2、I2C总线通信协议 3、 STM32F407的I2C接口 二、 I2C的HAL驱动程序 1、 I2C接口的初始化 2、阻塞式数据传输 (1)函数HAL_I2C_IsDeviceReady() (2)主设备发送和接收数据 &#…...
从头开始学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】
挑战:考古学家需要一种安全的方法来呈现新出土的陶瓷容器,对比文物形状。 解决方案:Artec Space Spider, Artec Studio 效果:本项目是REVERSEACTION项目的一部分,旨在研究无国家社会中复杂的古代技术。研究团队在考古地…...
《探索PyTorch计算机视觉:原理、应用与实践》
《探索PyTorch计算机视觉:原理、应用与实践》 一、PyTorch 与计算机视觉的奇妙相遇二、核心概念解析(一)张量:计算机视觉的数据基石(二)神经网络:视觉任务的智慧大脑(三)…...
【C#设计模式(21)——状态模式(State Pattern)】
前言 状态模式:在对象内部发生改变时改变其行为,使得对象在不同的状态下具有不同的行为表现。 代码 #region 状态模式-类/// 抽象 交通灯状态public abstract class TrafficLightState{public abstract void Display();}//红灯public class RedLight : TrafficLight…...
nvm日常使用中常用命令总结
日常开发vue项目中,不同的项目 我们可能需要安装不同的node版本,但是为了方便切换node,我们一般会安装一个名称为nvm的工具,这里总结一下,nvm常用的命令: 1、为了查看可用的 Node.js 版本,你可…...
【数据仓库】SparkSQL数仓实践
文章目录 集成hive metastoreSQL测试spark-sql 语法SQL执行流程两种数仓架构的选择hive on spark数仓配置经验 spark-sql没有元数据管理功能,只有sql 到RDD的解释翻译功能,所以需要和hive的metastore服务集成在一起使用。 集成hive metastore 在spark安…...
PessimisticLock
想象你和你的朋友都想去图书馆借同一本非常受欢迎的小说。为了确保你们中的一位能够成功借到这本书,图书馆采用了悲观锁机制来管理借阅过程。 悲观锁的方式 查看书籍状态:当你到达图书馆并决定要借这本小说时,你先告诉图书管理员你想借这本…...
【Maven】属性管理
1. 属性 问题导入 定义属性有什么好处? 1.1 属性配置与使用 ①:定义属性 <!--定义自定义属性--> <properties><spring.version>5.2.10.RELEASE</spring.version><junit.version>4.12</junit.version> </prop…...
微信小程序性能优化、分包
性能优化是任何应用开发中的重要组成部分,尤其是在移动环境中。对于微信小程序而言,随着用户量的增加和应用功能的丰富,性能优化显得尤为关键。良好的性能不仅提升用户体验,还能增加用户留存率和应用的使用频率。我们将探讨如何在…...
TDengine 新功能 VARBINARY 数据类型
1. 背景 VARBINARY 数据类型用于存储二进制数据,与 MySQL 中的 VARBINARY 数据类型功能相同,VARBINARY 数据类型长度可变,在创建表时指定最大字节长度,使用进按需分配存储,但不能超过建表时指定的最大值。 2. 功能说明…...
【Maven】工程依赖下载失败错误解决
在使用 Maven 构建项目时,可能会发生依赖项下载错误的情况,主要原因有以下几种: 下载依赖时出现网络故障或仓库服务器宕机等原因,导致无法连接至 Maven 仓库,从而无法下载依赖。 依赖项的版本号或配置文件中的版本号错…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...
