在QT中做有关于MySQL的业务时,有时候需要知道MySQL数据库的当前连接状态。但QT在提供的QSqlDatabase模块中并没有相关的功能,不像QTcpSocket在连接服务或断开服务时都有相应的信号发出。
-
(1)使用QSqlDatabase::
isOpen
()判断
经测试,在突然与数据库所在网络断开后,该接口仍返回true,不靠谱。
-
(2)设置连接参数setConnectOptions(“MYSQL_OPT_RECONNECT=1”)
未测试,看网上的说法是在长时间未操作(默认8小时)数据库则会与数据库断开,如设置这个参数则会重连,但不知道在断网后的情况怎样。
使用定时器,定时执行sql语句(“select 1”)来判断数据库是否连接正常。经测试,在突然断网的情况下,执行sql语句会阻塞20秒甚至更长的时间(
不知道这个时间是由什么决定的?可否设置?
);但若是数据库服务挂掉,则不会阻塞。
采用第3种方法 + 每次执行sql前ping一下网络是否连接正常,以此来避免断网时执行sql的阻塞。
(1)子线程中创建专门的连接来检测数据库连接状态;
(2)其他线程则创建自己的连接来执行相应的业务;并可根据子线程检测的状态结果来做相应的判断。
如果有别的方法,还请大佬们指导一下
#ifndef DBHEARTBEATTHREAD_H
#define DBHEARTBEATTHREAD_H
#include <QObject>
#include <QThread>
#include <QMap>
class DBHeartbeatThread : public QThread
Q_OBJECT
public:
enum DBType : quint8 {
MySQL = 0,
SqlServer,
Oracle
struct ConnectParam {
QString ip;
quint16 port;
QString dbName;
QString userName;
QString password;
public:
explicit DBHeartbeatThread(QObject *parent = nullptr);
explicit DBHeartbeatThread(const DBType &type, const ConnectParam ¶m, QObject *parent = nullptr);
public:
void setDBTypeAndConnectParm(const DBType &type, const ConnectParam ¶m);
void setCheckIpIsOnlineInterval(int msec);
void setConnectDBInterval(int msec);
void setCheckDBHeartbeatInterval(int msec);
QString lastError() const;
protected:
void run() override;
signals:
void signal_connectedDB();
void signal_disconnectedDB();
void signal_connectedNet();
void signal_disconnectedNet();
private:
DBType m_type;
ConnectParam m_param;
int m_checkIpIsOnlineInterval;
int m_connectDBInterval;
int m_checkDBHeartbeatInterval;
QMap<DBType, QString> m_mapDBTypeDriver;
QString m_lastError;
const int kCheckIpFailTime = 3;
const int kCheckDBFailTime = 3;
#endif
.cpp文件
#include "dbheartbeatthread.h"
#include <QDebug>
#include <QSqlError>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QTimer>
#include <QDateTime>
#include <QProcess>
DBHeartbeatThread::DBHeartbeatThread(QObject *parent) : QThread(parent)
m_checkIpIsOnlineInterval = 100;
m_connectDBInterval = 100;
m_checkDBHeartbeatInterval = 100;
m_lastError = "";
m_mapDBTypeDriver = {{MySQL, "QMYSQL"}, {SqlServer, "QODBC"}, {Oracle, "QOCI"}};
DBHeartbeatThread::DBHeartbeatThread(const DBType &type, const ConnectParam ¶m, QObject *parent)
: DBHeartbeatThread(parent)
m_type = type;
m_param = param;
void DBHeartbeatThread::setDBTypeAndConnectParm(const DBHeartbeatThread::DBType &type,
const DBHeartbeatThread::ConnectParam ¶m)
m_type = type;
m_param = param;
void DBHeartbeatThread::setCheckIpIsOnlineInterval(int msec)
m_checkIpIsOnlineInterval = msec;
void DBHeartbeatThread::setConnectDBInterval(int msec)
m_connectDBInterval = msec;
void DBHeartbeatThread::setCheckDBHeartbeatInterval(int msec)
m_checkDBHeartbeatInterval = msec;
QString DBHeartbeatThread::lastError() const
return m_lastError;
void DBHeartbeatThread::run()
QSqlDatabase db;
auto openDB = [&]() -> bool {
static QString connectName = "heartbeatCheck";
if (QSqlDatabase::contains(connectName)) {
db = QSqlDatabase::database(connectName);
} else {
db = QSqlDatabase::addDatabase(m_mapDBTypeDriver.value(m_type), connectName);
if (db.isOpen()) {
db.close();
db.setHostName(m_param.ip);
db.setPort(m_param.port);
db.setDatabaseName(m_param.dbName);
db.setUserName(m_param.userName);
db.setPassword(m_param.password);
QTime startTime = QTime::currentTime();
if (db.open()) {
QTime endTime = QTime::currentTime();
qDebug() << "数据库打开成功耗时: " << startTime.msecsTo(endTime) << "ms";
return true;
QTime endTime = QTime::currentTime();
qDebug() << "数据库打开失败耗时: " << startTime.msecsTo(endTime) << "ms";
m_lastError = QString("数据库打开失败,原因:%1").arg(db.lastError().text());
return false;
auto checkDBIsOnline = [&db]() -> bool {
QSqlQuery query(db);
QString sql = "select 1";
QTime startTime = QTime::currentTime();
if (query.exec(sql)) {
return true;
QTime endTime = QTime::currentTime();
qDebug() << "检测心跳断开耗时:" << startTime.msecsTo(endTime) << "ms";
return false;
auto checkIpIsOnline = [](const QString & ip) -> bool {
QProcess cmd;
QString command = "";
#ifdef Q_OS_WIN
command = QString("ping %1 -n 1 -w 1000").arg(ip);
#else
command = QString("ping -s 1 -c 1 %1").arg(ip);
#endif
cmd.start(command);
cmd.waitForFinished(1000 * 1);
QString retStr = cmd.readAll();
if (retStr.indexOf("ttl", 0, Qt::CaseInsensitive) == -1) {
return false;
return true;
QTimer timerCheckIp;
QTimer timerConnectDB;
QTimer timerDBHeartbeat;
timerCheckIp.setInterval(m_checkIpIsOnlineInterval);
connect(&timerCheckIp, &QTimer::timeout, [&] {
timerCheckIp.stop();
if (checkIpIsOnline(m_param.ip)) {
qDebug() << "连接网络成功,正在连接数据库";
emit signal_connectedNet();
timerConnectDB.start();
} else {
timerCheckIp.start();
});
timerConnectDB.setInterval(m_connectDBInterval);
connect(&timerConnectDB, &QTimer::timeout, [&] {
timerConnectDB.stop();
if (checkIpIsOnline(m_param.ip)) {
if (openDB()) {
qDebug() << "连接数据库成功,开始心跳检测";
emit signal_connectedDB();
timerDBHeartbeat.start();
} else {
timerConnectDB.start();
} else {
qDebug() << "网络断开,正在重连";
emit signal_disconnectedNet();
timerCheckIp.start();
});
timerDBHeartbeat.setInterval(m_checkDBHeartbeatInterval);
connect(&timerDBHeartbeat, &QTimer::timeout, [&] {
static int checkIpFailTime = 0;
static int checkDBFailTime = 0;
timerDBHeartbeat.stop();
if (checkIpIsOnline(m_param.ip)) {
checkIpFailTime = 0;
if (checkDBIsOnline()) {
checkDBFailTime = 0;
timerDBHeartbeat.start();
} else {
++checkDBFailTime;
if (checkDBFailTime == kCheckDBFailTime) {
checkDBFailTime = 0;
qDebug() << "数据库断开,正在重连";
emit signal_disconnectedDB();
timerConnectDB.start();
} else {
timerDBHeartbeat.start();
} else {
++checkIpFailTime;
if (checkIpFailTime == kCheckIpFailTime) {
checkIpFailTime = 0;
qDebug() << "网络断开,正在重连";
emit signal_disconnectedNet();
timerCheckIp.start();
} else {
timerDBHeartbeat.start();
});
timerCheckIp.start();
qDebug() << "正在连接网络";
exec();
在QT中做有关于MySQL的业务时,有时候需要知道MySQL数据库的当前连接状态。但QT在提供的QSqlDatabase模块中并没有相关的功能,不像QTcpSocket在连接服务或断开服务时都有相应的信号发出。
//连接数据库bool scoreWindow::createConnection()
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setDatabaseName("test");//数据库的名称
db.setUserName("roo
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "a");
db.setConnectOptions("MYSQL_OPT_RECONNECT=1");
PyQt 有内置的数据库连接类 QtSql 。
在使用 PyQt 连接 MySql 展示数据时,如果明确所有数据库操作都与 Qt 窗口有关,且不涉及复杂的数据操作,则可以使用内置的 QtSql 类。不需要安装额外的数据库类,且能更加便利的与 QtTableView 等 Qt 控件进行数据交互。
db = QtSql.QSqlDatabase.addDatabase('QMYSQL')
db.setHostName('localhost')
db.setDatabaseName('dev')
db.setUserName('root')
db.setPassword('123')
1. 调用addDatabase();函数:确定你要连接的数据库驱动。我这里用的是Oracle数据库所以是“QOCI”,使用mysql数据库的话自然是"QMYSQL"等等,要选择自己数据库对应的驱动。
2. 调用setHostName();函数:数据库的ip地址,当然如果是你自...
QSqlDatabase:可以提供默认连接供Qt其他的SQL类使用。
第一次.据库的连接 用到QSqlDatabase 以及其类中的:: database和 addDatabase,
QString g_sThreadId;
QSqlDatabase db = QSqlDatabase::database(g_sThreadId);
if (! db.isValid()) {
// 参数1为驱动名,参数2名连
1、关于UDP的基础信息
UDP(user datagram protocol,用户数据报协议)是轻量的、不可靠的、面向数据报(datagram)、无连接的协议,它可以用于对可靠性要求不高的场合。与TCP通信不同,两个程序之间进行UDP通信无需预先建立持久的socket连接,UDP每次发送数据报都需要指定目标地址和端口。 UDP通信相对于TCP通信的实现来说就稍微容易一些了,因为UDP是不需要分客户端和服务器的。只需要用到一个类QUdpSocket。
UDP消息传送有单播、广播、组播三种模式。
单播(un
在 Qt 中实现 TCP 连接失败重连和断开重连,可以通过以下步骤实现:
1. 创建一个 `QTcpSocket` 实例,并连接 `error(QAbstractSocket::SocketError)` 信号和 `disconnected()` 信号。
```cpp
QTcpSocket *socket = new QTcpSocket(this);
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
connect(socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
2. 在 `onError(QAbstractSocket::SocketError)` 槽函数中实现重连逻辑。当连接出现错误时,可以通过调用 `QTcpSocket::state()` 函数来获取当前连接状态。
```cpp
void MyServer::onError(QAbstractSocket::SocketError error)
if (socket->state() == QAbstractSocket::UnconnectedState) {
socket->connectToHost("127.0.0.1", 12345); // 重连
3. 在 `onDisconnected()` 槽函数中实现断开重连逻辑。当连接断开时,可以通过调用 `QTcpSocket::state()` 函数来获取当前连接状态。
```cpp
void MyServer::onDisconnected()
if (socket->state() == QAbstractSocket::UnconnectedState) {
socket->connectToHost("127.0.0.1", 12345); // 断开重连
通过以上步骤,就可以在 Qt 中实现 TCP 连接失败重连和断开重连的功能了。