QT实现TCP客户端自动连接

2024-12-30 15:50

本文主要是介绍QT实现TCP客户端自动连接,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《QT实现TCP客户端自动连接》这篇文章主要为大家详细介绍了QT中一个TCP客户端自动连接的测试模型,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下...

版本 1:没有取消按钮

 测试效果

QT实现TCP客户端自动连接

缺陷:

无法手动停止

测试代码

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));
            }python
        }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__<www.chinasem.cn<__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:有取消按钮

测试效果

QT实现TCP客户端自动连接

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

QT实现TCP客户端自动连接

测试代码

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 www.chinasem.cnMyPushButton:public QPushButton{China编程
    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,dialjsog](){
                          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客户端自动连接的详细内容,更多关于QT TCP客户端的资料请关注China编程(www.chinasem.cn)其它相关文章!

这篇关于QT实现TCP客户端自动连接的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1152849

相关文章

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四:

IDEA中新建/切换Git分支的实现步骤

《IDEA中新建/切换Git分支的实现步骤》本文主要介绍了IDEA中新建/切换Git分支的实现步骤,通过菜单创建新分支并选择是否切换,创建后在Git详情或右键Checkout中切换分支,感兴趣的可以了... 前提:项目已被Git托管1、点击上方栏Git->NewBrancjsh...2、输入新的分支的

Python实现对阿里云OSS对象存储的操作详解

《Python实现对阿里云OSS对象存储的操作详解》这篇文章主要为大家详细介绍了Python实现对阿里云OSS对象存储的操作相关知识,包括连接,上传,下载,列举等功能,感兴趣的小伙伴可以了解下... 目录一、直接使用代码二、详细使用1. 环境准备2. 初始化配置3. bucket配置创建4. 文件上传到os

Qt QCustomPlot库简介(最新推荐)

《QtQCustomPlot库简介(最新推荐)》QCustomPlot是一款基于Qt的高性能C++绘图库,专为二维数据可视化设计,它具有轻量级、实时处理百万级数据和多图层支持等特点,适用于科学计算、... 目录核心特性概览核心组件解析1.绘图核心 (QCustomPlot类)2.数据容器 (QCPDataC

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

java实现docker镜像上传到harbor仓库的方式

《java实现docker镜像上传到harbor仓库的方式》:本文主要介绍java实现docker镜像上传到harbor仓库的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 前 言2. 编写工具类2.1 引入依赖包2.2 使用当前服务器的docker环境推送镜像2.2

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Java easyExcel实现导入多sheet的Excel

《JavaeasyExcel实现导入多sheet的Excel》这篇文章主要为大家详细介绍了如何使用JavaeasyExcel实现导入多sheet的Excel,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录1.官网2.Excel样式3.代码1.官网easyExcel官网2.Excel样式3.代码

python实现对数据公钥加密与私钥解密

《python实现对数据公钥加密与私钥解密》这篇文章主要为大家详细介绍了如何使用python实现对数据公钥加密与私钥解密,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录公钥私钥的生成使用公钥加密使用私钥解密公钥私钥的生成这一部分,使用python生成公钥与私钥,然后保存在两个文