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

相关文章

java poi实现Excel多级表头导出方式(多级表头,复杂表头)

《javapoi实现Excel多级表头导出方式(多级表头,复杂表头)》文章介绍了使用javapoi库实现Excel多级表头导出的方法,通过主代码、合并单元格、设置表头单元格宽度、填充数据、web下载... 目录Java poi实现Excel多级表头导出(多级表头,复杂表头)上代码1.主代码2.合并单元格3.

Python读取TIF文件的两种方法实现

《Python读取TIF文件的两种方法实现》本文主要介绍了Python读取TIF文件的两种方法实现,包括使用tifffile库和Pillow库逐帧读取TIFF文件,具有一定的参考价值,感兴趣的可以了解... 目录方法 1:使用 tifffile 逐帧读取安装 tifffile:逐帧读取代码:方法 2:使用

Spring Boot实现多数据源连接和切换的解决方案

《SpringBoot实现多数据源连接和切换的解决方案》文章介绍了在SpringBoot中实现多数据源连接和切换的几种方案,并详细描述了一个使用AbstractRoutingDataSource的实... 目录前言一、多数据源配置与切换方案二、实现步骤总结前言在 Spring Boot 中实现多数据源连接

Mybatis拦截器如何实现数据权限过滤

《Mybatis拦截器如何实现数据权限过滤》本文介绍了MyBatis拦截器的使用,通过实现Interceptor接口对SQL进行处理,实现数据权限过滤功能,通过在本地线程变量中存储数据权限相关信息,并... 目录背景基础知识MyBATis 拦截器介绍代码实战总结背景现在的项目负责人去年年底离职,导致前期规

使用 Python 和 LabelMe 实现图片验证码的自动标注功能

《使用Python和LabelMe实现图片验证码的自动标注功能》文章介绍了如何使用Python和LabelMe自动标注图片验证码,主要步骤包括图像预处理、OCR识别和生成标注文件,通过结合Pa... 目录使用 python 和 LabelMe 实现图片验证码的自动标注环境准备必备工具安装依赖实现自动标注核心

使用Python实现生命之轮Wheel of life效果

《使用Python实现生命之轮Wheeloflife效果》生命之轮Wheeloflife这一概念最初由SuccessMotivation®Institute,Inc.的创始人PaulJ.Meyer... 最近看一个生命之轮的视频,让我们珍惜时间,因为一生是有限的。使用python创建生命倒计时图表,珍惜时间

python-nmap实现python利用nmap进行扫描分析

《python-nmap实现python利用nmap进行扫描分析》Nmap是一个非常用的网络/端口扫描工具,如果想将nmap集成进你的工具里,可以使用python-nmap这个python库,它提供了... 目录前言python-nmap的基本使用PortScanner扫描PortScannerAsync异

python与QT联合的详细步骤记录

《python与QT联合的详细步骤记录》:本文主要介绍python与QT联合的详细步骤,文章还展示了如何在Python中调用QT的.ui文件来实现GUI界面,并介绍了多窗口的应用,文中通过代码介绍... 目录一、文章简介二、安装pyqt5三、GUI页面设计四、python的使用python文件创建pytho

基于Redis有序集合实现滑动窗口限流的步骤

《基于Redis有序集合实现滑动窗口限流的步骤》滑动窗口算法是一种基于时间窗口的限流算法,通过动态地滑动窗口,可以动态调整限流的速率,Redis有序集合可以用来实现滑动窗口限流,本文介绍基于Redis... 滑动窗口算法是一种基于时间窗口的限流算法,它将时间划分为若干个固定大小的窗口,每个窗口内记录了该时间

Python模块导入的几种方法实现

《Python模块导入的几种方法实现》本文主要介绍了Python模块导入的几种方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录一、什么是模块?二、模块导入的基本方法1. 使用import整个模块2.使用from ... i