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

news2024/12/28 16:14:17

版本 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(AutoConnect
    WIN32 MACOSX_BUNDLE
    main.cpp

    widget.h
    widget.ui
)

target_link_libraries(AutoConnect
    PRIVATE
        Qt::Core
        Qt::Widgets
        Qt6::Network
)

include(GNUInstallDirs)

install(TARGETS AutoConnect
    BUNDLE  DESTINATION .
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

qt_generate_deploy_app_script(
    TARGET AutoConnect
    OUTPUT_SCRIPT deploy_script
    NO_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_OBJECT

public:
    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(AutoConnect
    WIN32 MACOSX_BUNDLE
    main.cpp

    widget.h
    widget.ui
)

target_link_libraries(AutoConnect
    PRIVATE
        Qt::Core
        Qt::Widgets
        Qt6::Network
)

include(GNUInstallDirs)

install(TARGETS AutoConnect
    BUNDLE  DESTINATION .
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

qt_generate_deploy_app_script(
    TARGET AutoConnect
    OUTPUT_SCRIPT deploy_script
    NO_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_OBJECT

public:
    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

小结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2267002.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp中wx.getFuzzyLocation报错如何解决

一、用wx.getLocation接口审核不通过 用uniapp开发小程序时难免需要获取当前地理位置。 代码如下&#xff1a; uni.getLocation({type: wgs84,success: function (res) {console.log(当前位置的经度&#xff1a; res.longitude);console.log(当前位置的纬度&#xff1a; r…

解决Ubuntu下无法装载 Windows D盘的问题

电脑安装了 Windows 和 Ubuntu 24.04 后&#xff0c;在Ubuntu系统上装载 D盘&#xff0c;发现无法装载错误如下&#xff1a; Error mounting /dev/nvme0n1p4 at /media/jackeysong/Data: wrong fs type, bad option, bad superblock on /dev/nvme0n1p4, missing codepage or h…

硬件设计-高速电路的过孔

目录 摘要 &#xff1a; 过孔的机械特性&#xff1a; 过孔直径&#xff1a; 过孔焊盘尺寸 摘要 &#xff1a; 过孔这个词指得是印刷电路板&#xff08; PCB &#xff09;上的孔。过孔可以用做焊接插装器件的焊&#xff08; Through hole) &#xff0c;也可用做连接层间走…

mysql索引的理解

1、索引是什么&#xff1f; 索引&#xff1a;简单理解就是我们字典的目录&#xff0c;一个索引可以找得到多个记录。 作用加快我们数据库的查询速度。索引本身较大&#xff0c;往往存储在磁盘的文件里。可能存储在单独的索引文件中&#xff0c;也可能和数据一起存储在数据文件…

【WRF模拟】如何得到更佳的WRF模拟效果?

【WRF模拟】如何得到更佳的WRF模拟效果&#xff1f; 模型配置&#xff08;The Model Configuration&#xff09;1.1 模拟区域domain设置1.2 分辨率Resolution (horizontal and vertical)案例&#xff1a;The Derecho of 29-30 June 2012 1.3 初始化和spin-up预热过程案例1-有无…

IOS safari 播放 mp4 遇到的坎儿

起因 事情的起因是调试 IOS 手机下播放服务器接口返回的 mp4 文件流失败。对于没调试过移动端和 Safari 的我来说着实费了些功夫&#xff0c;网上和AI也没有讲明白。好在最终大概理清楚了&#xff0c;在这里整理出来供有缘人参考。 问题 因为直接用 IOS 手机的浏览器打开页面…

单片机+人体红外感应的防盗系统设计(仿真+源码+PCB文件+报告)

资料下载地址&#xff1a;单片机人体红外感应的防盗系统设计(仿真源码PCB文件报告) 1、功能介绍 (1)该设计包括硬件和软件设计两个部分。 (2)本红外线防盗报警系统由热释电红外传感器、报警器、单片机控制电路、LED控制电路及相关的控制管理软件组成。用户终端完成信息采集、处…

网络攻防实践

1. 学习总结 黛蛇蠕虫案例&#xff1a; 原理&#xff1a;利用系统漏洞&#xff0c;并集成攻击代码。其中&#xff0c;通过蜜罐技术并进行数据分析所获取的攻击场景如下&#xff1a; 外部感染源攻陷蜜罐主机 执行Shellcode后获取主机权限后连接控制命令服务器&#xff0c;获取F…

寒假准备找实习复习java基础-day1

CMD常用命令&#xff1a; java跨平台原理&#xff1a; JRE和JVM Java基本数据类型

MacOS安装Xcode(非App Store)

文章目录 访问官网资源页面 访问官网资源页面 直接访问官网的历史版本下载资源页面地址&#xff1a;https://developer.apple.com/download/more/完成APP ID的登陆&#xff0c;直接找到需要的软件下载即可 解压后&#xff0c;安装将xcode.app移动到应用程序文件夹。

Docker 安装mysql ,redis,nacos

一、Mysql 一、Docker安装Mysql 1、启动Docker 启动&#xff1a;sudo systemctl start dockerservice docker start 停止&#xff1a;systemctl stop docker 重启&#xff1a;systemctl restart docker 2、查询mysql docker search mysql 3、安装mysql 3.1.默认拉取最新版…

gitlab克隆仓库报错fatal: unable to access ‘仓库地址xxxxxxxx‘

首次克隆仓库&#xff0c;失效了&#xff0c;上网查方法&#xff0c;都说是网络代理的问题&#xff0c;各种清理网络代理后都无效&#xff0c;去问同事&#xff1a; 先前都是直接复制的网页url当做远端url&#xff0c;或者点击按钮‘使用http克隆’ 这次对于我来说有效的远端u…

RK356x bsp 7 - PCF8563 RTC调试记录

文章目录 1、环境介绍2、目标3、PCF85634、dts配置5、内核配置6、测试验证 1、环境介绍 硬件&#xff1a;飞凌ok3568-c开发板 软件&#xff1a;原厂rk356x sdk 2、目标 开发板断电后仍正常计时。 3、PCF8563 PCF8563 是由 NXP Semiconductors 公司生产的低功耗 CMOS 实时…

图研院 | 掌握前沿图技术,从 “Graph XAI” 课程起航

在如今数字化转型加速的时代浪潮下&#xff0c; 图数据库技术正成为众多领域突破创新的关键力量&#xff01; 你是否也渴望深入了解其背后的核心知识&#xff0c; 开启自己的图技术进阶之旅&#xff1f; 由机工社精心打造的系列大师课&#xff0c; 特邀国际级专家/学者师资…

Oracle考试多少分算通过?

OCP和OCM认证的考试及格分数并不是固定的&#xff0c;而是根据考试的难度和考生的整体表现来确定。对于OCP认证&#xff0c;考生需要全面掌握考试要求的知识和技能&#xff0c;并在考试中表现出色才有可能通过。而对于OCM认证&#xff0c;考生则需要在每个模块中都达到一定的水…

01.HTTPS的实现原理-HTTPS的概念

01.HTTPS的实现原理-HTTPS的概念 简介1. HTTPS的概念和安全性2. HTTPS的实现原理3. HTTPS和HTTP的区别4. OSI七层协议模型5. SSL和TLS的区别 简介 该系列文章主要讲述了HTTPS协议与HTTP协议的区别&#xff0c;以及HTTPS如何实现安全传输。内容分为三部分&#xff1a;HTTPS的实…

教师管理系统

大概功能&#xff1a; 1.显示所有教师 2.按姓名查找教师 3.按工号查找教师 4.增加教师 5.删除教师 6.退出 数据会保存到 txt 文件里面 姓名&#xff1a;必须是中文 手机号码&#xff1a;必须是11位&#xff0c;必须是数字 效果展示&#xff1a; 代码展示&#xff1a; Teache…

CSES-1687 Company Queries I(倍增法)

题目传送门https://vjudge.net/problem/CSES-1687#authorGPT_zh 解题思路 其实和倍增法求 LCA 是一样的…… 首先设 表示 号点的上面的第 个祖先是谁。 同倍增法&#xff1a; 然后&#xff0c;题目要求我们向上跳 个点。 枚举 &#xff08;从大到小&#xff0c;想想为…

自动驾驶控制算法-横向误差微分方程LQR前馈控制

本文是学习自动驾驶控制算法第六讲 前馈控制与航向误差以及前两节的学习笔记。 1 横向误差微分方程 以规划的轨迹作为自然坐标系&#xff0c;计算自车在轨迹上的投影点&#xff0c;进而计算误差&#xff1a; 如图所示&#xff0c;横向误差为 d d d&#xff0c;航向误差为 θ…

后端开发如何高效使用 Apifox?

Apifox 是一个 API 协作开发平台&#xff0c;后端、前端、测试都可以使用 Apifox 来提升团队的工作效率。对于后端开发者而言&#xff0c;Apifox 的核心功能主要包括四个模块&#xff1a;调用 API、定义 API、开发与调试 API 以及生成 API 文档。本文将详细介绍后端开发人员如何…