在现在的项目开发中,经常要使用TCP/IP协议来进行通讯,但有时候与服务器端的链接由于网络问题导致连接异常或断开,这就需要我们的软件能自动重连,在Linux中,我们的思维一般是通过心跳包来监控连接是否断开,有时候还单独开一个线程,但是在QT中,就变得简单多了,当连接异常断开时,会触发相应的信号,我们只要在这个信号对应的槽函数中做重连处理就可以了,不需要另开线程也不需要心跳包。由于网上查的QT重连服务器端,大多都是通过建立的线程去实现,我觉得比较麻烦,这里就记录下我自己的思路:使用定时器QTimer或定时器事件QTimerEvent,来实现重连,当当前的连接断开时,QT便会发送 disconnected()信号,我们在这个信号对应的槽函数中开启定时器,重连的操作就放在定时器对应的槽函数中执行(或重写的定时器事件中执行),当重连成功后,QT会发送connected()信号,此时我们在其对应的槽函数中关闭定时器即可。

下边直接来贴代码,我们是建了一个简单的clientt类,来做一个Socket客户端,首先是头文件client.h文件

#ifndef CLIENT_H
#define CLIENT_H#include <QtWidgets/QWidget>
#include <QtNetwork>
#include <QtNetwork/QTcpSocket>
#include <QLineEdit>
#include <QTextEdit>
#include <QPushButton>
#include <QLabel>
#include <QTimerEvent>
#include <QTimer>class Client : public QWidget
{Q_OBJECTpublic:Client(QWidget *parent = 0);~Client();private://方式一:使用定时器事件实现socket重连int m_TimerID; //定时器事件IDvoid timerEvent(QTimerEvent * event); //需要重写改定时器事件函数//方式二:使用定时器实现重连QTimer m_Timer; protected:void init();  //UI初始化void newTCPConnect();    //建立一个新连接private slots: void clientReadData();  //几个Socket连接相关的槽函数void clientConnected();void clientDisconnected();void clientError(QAbstractSocket::SocketError socketError);void clientStateChange(QAbstractSocket::SocketState socketState);void onConnectButtonClicked();void slotTimeOut();private:bool m_IsConnected;QTcpSocket *tcpSocket;QPushButton m_ConnectButton;QLabel m_IPLabel;QLabel m_PortLabel;QLineEdit m_IPEdit;QLineEdit m_PortEdit;QTextEdit m_TextEdit;
};#endif // CLIENT_H

下边是client.cpp文件

#include "Client.h"#include <QHostAddress>
#include <QFormLayout>
#include <QHBoxLayout>
#include <QVBoxLayout>#include <QDebug>Client::Client(QWidget *parent)  : QWidget(parent), m_IsConnected(false)
{this->setFixedSize(500, 300);init();
}void Client::init()
{m_IPLabel.setParent(this);m_IPLabel.setText("IP");m_PortLabel.setParent(this);m_PortLabel.setText("Port");m_IPEdit.setParent(this);m_IPEdit.setText("127.0.0.1");m_PortEdit.setParent(this);m_PortEdit.setText("5000");m_ConnectButton.setParent(this);m_ConnectButton.setText("connect");m_TextEdit.setParent(this);QFormLayout *fLayout1 = new QFormLayout;fLayout1->addRow(&m_IPLabel, &m_IPEdit);QFormLayout *fLayout2 = new QFormLayout;fLayout2->addRow(&m_PortLabel, &m_PortEdit);QHBoxLayout *hLayout = new QHBoxLayout;hLayout->addLayout(fLayout1);hLayout->addLayout(fLayout2);hLayout->addWidget(&m_ConnectButton);QVBoxLayout *vLayout = new QVBoxLayout;vLayout->addLayout(hLayout);vLayout->addWidget(&m_TextEdit);this->setLayout(vLayout);tcpSocket = new QTcpSocket(this);connect(&m_ConnectButton, SIGNAL(clicked()), this, SLOT(onConnectButtonClicked()));connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(clientReadData()));connect(tcpSocket, SIGNAL(connected()), this, SLOT(clientConnected()));connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(clientStateChange(QAbstractSocket::SocketState)));connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(clientError(QAbstractSocket::SocketError)));connect(&m_Timer, SIGNAL(timeout()), this, SLOT(slotTimeOut()));}void Client::newTCPConnect()
{tcpSocket->abort();QHostAddress address = QHostAddress(m_IPEdit.text());unsigned int port = m_PortEdit.text().toInt();tcpSocket->connectToHost(address, port);if (!tcpSocket->waitForConnected(3000)) //连接时长为3s,超过3秒连不上则输出错误信息{}
}//接收数据
void Client::clientReadData()
{QString msg = "\nrecieve msg : " + tcpSocket->readAll();m_TextEdit.append(msg);tcpSocket->write("GET");
}//连接成功是时调用
void Client::clientConnected()
{m_Timer.stop();        //连接成功后定时器停止//killTimer(m_TimerID); //连接成功后终止对应ID的定时器事件m_IsConnected = true;QString msg = "server IP : " + tcpSocket->peerAddress().toString();m_TextEdit.append(msg);msg = "server Port : " + QString::number(tcpSocket->peerPort());m_TextEdit.append(msg);m_ConnectButton.setText("disconnect");m_ConnectButton.setStyleSheet("background-color: green");//当重连成功时,可以根据具体情况恢复软件的一些工作}//连接断开时调用
void Client::clientDisconnected()
{m_Timer.start(2000);   //连接断开时开启定时器,定时时间为2s//m_TimerID = startTimer(2000); //连接断开时开始一个定时器事件,并将ID赋给m_TimerIDm_IsConnected = false;m_ConnectButton.setText("connect");m_ConnectButton.setStyleSheet("background-color: red");//当连接断开时,可以根据具体情况决定是否停止软件当前的一些工作,比方暂停测试什么的
}//获取socket错误信息
void Client::clientError(QAbstractSocket::SocketError socketError)
{m_IsConnected = false;tcpSocket->close();
}//连接状态发生改变时获取其状态
void Client::clientStateChange(QAbstractSocket::SocketState socketState)
{
#if 0if (socketState == QAbstractSocket::UnconnectedState){m_TextEdit.append("clientState : UnconnectedState");}else if (socketState == QAbstractSocket::HostLookupState){m_TextEdit.append("clientState : HostLookupState");}else if (socketState == QAbstractSocket::ConnectedState){m_TextEdit.append("clientState : ConnectedState");}else if (socketState == QAbstractSocket::ConnectingState){m_TextEdit.append("clientState : ConnectingState");}else if (socketState == QAbstractSocket::ClosingState){m_TextEdit.append("clientState : ClosingState");}
#endif
}void Client::onConnectButtonClicked()
{m_TextEdit.append("");if (m_ConnectButton.text() == "disconnect"){tcpSocket->disconnectFromHost();}else if(m_ConnectButton.text() == "connect"){newTCPConnect();}
}void Client::timerEvent(QTimerEvent * event)
{if (event->timerId()  == m_TimerID)   //在定时器事件中重连服务器{if (!m_IsConnected){m_TextEdit.append(QString::fromLocal8Bit("重连服务器..."));newTCPConnect();}}
}//使用定时器来重连服务器
void Client::slotTimeOut()
{if (!m_IsConnected){m_TextEdit.append(QString::fromLocal8Bit("重连服务器..."));newTCPConnect();}
}Client::~Client()
{}

主程序中直接使用这个类:

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

编译运行:

刚开始与服务器端正常连接并接收数据hello sokect,然后我关掉服务器,于是客户端便进行重连...,后边重开服务器,客户端便重连成功。

上边是把定时器事件给屏蔽了,使用定时器来实现,也可以把定时器屏蔽,使用定时器事件进行重连,具体视项目情况而定。

QT 中Socket客户端与服务器异常断开后重连相关推荐

  1. Socket 客户端判断服务器是否断开连接

    //  首先,Socket类的Connected属性只表示最后一次I/O操作的状态,如果这之后[连接的另一方]断开了,它还一直返回true, 除非你再通过socket来发送数据.所以通过个属性来判断是 ...

  2. 社保管理系统连接不上服务器,社保费客户端登录服务器异常

    社保费客户端登录服务器异常 内容精选 换一换 本章节以Linux操作系统为例,指导您通过弹性云服务器内网方式连接GaussDB(for Redis)实例.使用内网连接GaussDB(for Redis ...

  3. 查询社保信息显示内部服务器错误,社保费客户端登录服务器异常

    社保费客户端登录服务器异常 内容精选 换一换 当出现以下问题时,可以参考本章节排查解决.可以直接访问后端业务,但是无法通过负载均衡访问后端业务.通过私网IP可以访问负载均衡,但是公网IP无法访问负载均 ...

  4. 邯郸社保认证显示服务器异常,社保费客户端登录服务器异常

    社保费客户端登录服务器异常 内容精选 换一换 业界对备份一致性的定义包括如下三类:不一致备份:备份的文件.磁盘不在同一个时间点.崩溃一致性备份:崩溃一致性备份会捕获备份时磁盘上已存在的数据,文件/磁盘 ...

  5. C# Socket客户端采用双线程断网重连断线重连)

    C# Socket客户端采用双线程断网重连断线重连 2021年07月15日 13:38:18更新 C# Socket服务端 双线程断网重连断线重连 C# Socket客户端采用双线程断网重连断线重连 ...

  6. qt中socket编程

    1 文章概括 在qt中借助designer设计通信界面,然后使用QTcpServer,QTcpSocket编写服务器和客户端的程序. 首先建立两个工程,一个是客户端client,另一个是服务器端ser ...

  7. socket客户端和服务器通信协议,51. Socket服务端和客户端使用TCP协议通讯

    Socket服务器是网络服务中常用的服务器.使用 go 语言实现这个业务场景是很容易的. 这样的网络通讯,需要一个服务端和至少一个客户端. 我们计划构建一个这样的通讯过程.服务端启动后等待客户端的访问 ...

  8. 微信小程序蓝牙连接硬件设备并进行通讯,小程序蓝牙因距离异常断开自动重连,js实现crc校验位

    一.小程序实现搜索蓝牙: 注意:comtl是我封装的工具函数,无关紧要,实际项目中可能用不到: const comtl = require('../../utils/commontool') cons ...

  9. windows卸载qt_如何在Qt中显示一个窗口并在关闭后立即将其删除?

    作为一个非常简单的例子,我想在按下按钮时在Qt中显示一个对话框.通常的模式(在我正在申请的应用程序中)似乎如下: class MainWindow { ... private slots: butto ...

最新文章

  1. Discuz! 防御CC攻击的设置办法
  2. synchronized与volatile
  3. 1.2编程基础之变量定义、赋值及转换 10 Hello, World 的大小
  4. (转)Hibernate的一级缓存
  5. Django:ORM基本操作-CRUD,管理器对象objects,----->查询1(all,values,values_list,order_by)
  6. SpringBoot+SpringCloud —— 使用Feign消费服务
  7. Java 性能优化系列之3.2[JVM调优]
  8. 阿里影业“灯塔平台”今日正式启动,阿里影视云解决方案强势推出
  9. 3726.调整数组-AcWing题库
  10. PHP之Seay工具的安装与使用
  11. 雷达、信号处理方向的理解
  12. 庄懂shader入门系列-菲尼尔 立方体贴图 MatCap
  13. 欧姆龙PLC HostLink协议整理
  14. 小程序电子名片 制作
  15. Graphene图数据建模工具
  16. 西安交大计算机系96年录取分数,西安交通大学2018年各省录取分数线
  17. 操作系统实验指导书(完整版)
  18. Java 变态面试题
  19. 去哪儿网首页-周末游组件开发(6)
  20. LeetCode总结——题1313、66、169、209

热门文章

  1. 基于OpenVINO部署PaddlePadle-YOLOE模型—2.模型下载与转换
  2. uva 378Intersecting Lines
  3. 小傻蛋的妹妹跟随小甲鱼学习Python的第十七节017
  4. netty整合shiro,报There is no session with id [xxxxxx]问题定位及解决
  5. Code Embedding研究系列11-ContraFlow
  6. 大学生如何在竞争激烈的就业市场中脱颖而出
  7. C++11新特性总结
  8. ES-Module导入导出配合使用
  9. 网站标准/CMS/ADS....
  10. 安卓动态调试七种武器之孔雀翎 – Ida Pro – 蒸米