资源连接:https://download.csdn.net/download/smalbig/12302458
未经允许请勿转载。
架构和实现:每当有一个新的入库请求时,服务器新建一个线程,线程内new一个QTcpSocket用来接收终端的数据,线程内新建一个数据库连接。在服务器内实现互不干扰,独立入库的功能。
线程安全,工业信息采集实际项目代码,单终端每秒500条类似“22 33 44 55”格式的数据,多终端则倍增,最大速度受制于处理器。
关键代码:
响应新连接类:
class FortuneServer : public QTcpServer
{
Q_OBJECT
public:
FortuneServer(QObject *parent = 0);
protected:
void incomingConnection(qintptr socketDescriptor) override;
};
响应新连接实现关键代码:重写了QTcpServer中的incomingConnection函数,当有新tcp连接时该函数被调用。在该函数中new了一个FortuneThread类的线程,该线程内用来执行获取终端传来的消息,并把消息入库的操作。
FortuneServer::FortuneServer(QObject *parent)
: QTcpServer(parent)
{
}
int linkNum = 0;//数据库连接名自增
void FortuneServer::incomingConnection(qintptr socketDescriptor){
FortuneThread *thread = new FortuneThread(socketDescriptor, "",QString::number(linkNum), this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
linkNum += 1;
}
线程类:
#ifndef FORTUNETHREAD_H
#define FORTUNETHREAD_H
#include <iostream>
#include <QtSql>
#include <QThread>
#include <QTcpSocket>
#include <QtNetwork>
#include <QMutex>
//! [0]
#pragma execution_character_set("utf-8")
class FortuneThread : public QThread
{
Q_OBJECT
public:
FortuneThread(int socketDescriptor, const QString &fortune,QString LINKNUM, QObject *parent);
void run() override;
signals:
void error(QTcpSocket::SocketError socketError);
private:
QMutex mutex;
QTcpSocket *tcpSocket;
int socketDescriptor;
bool m_stop = false;
};
线程实现:
#include "fortunethread.h"
#include <QtNetwork>
#include <Qdir>
#include <QFile>
#include <QFileDialog>
#include <QTextStream>
#include <QTextCodec>
#include <QString>
#include <QDateTime>
#include <QQueue>
//! [0]
//extern QSqlDatabase db;
QStringList resultList;
bool dbopen;
int num = 0;
extern int linkNum;
QQueue<QByteArray> queue;
FortuneThread::FortuneThread(int socketDescriptor, const QString &fortune, QString LINKNUM,QObject *parent)
: QThread(parent), socketDescriptor(socketDescriptor), text(fortune)
{
SingleLINKNUM = LINKNUM;
}
void FortuneThread::run()
{
tcpSocket = new QTcpSocket();
if (!tcpSocket->setSocketDescriptor(socketDescriptor)) {
emit error(tcpSocket->error());
return;
}
//事件循环
msleep(500);//可有效缓解并发链接问题
eventloop = new QEventLoop();
connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(onreadyread()),Qt::DirectConnection);
connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(ondisconnect()),Qt::DirectConnection);
eventloop->exec();
linkNum -= 1;
//断开一次链接则链接数减一,给新的连接留出位置。
。
。
。
。
。
}
void FortuneThread::onreadyread(){
//
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL",SingleLINKNUM);//增加新连接
db.setHostName("localhost");
db.setDatabaseName("world");
db.setUserName("root");
db.setPassword("1234");
。
。
。
。
。
。
。
QSqlQuery querysql(db);//QSqlQuery querysql(db),记住加上数据库名称
。
。
。
。
。
。
inmsg = tcpSocket->readAll();
QString msg = inmsg.data();
querysql.prepare("insert into city values(?,?,?,?,?);");
if(bindVals.size()>3){
querysql.bindValue(1,bindVals[1]);
querysql.bindValue(2,bindVals[2]);
querysql.bindValue(3,bindVals[3]);
querysql.bindValue(4,datetime);
}
querysql.exec();
}
}
}
mutex.unlock();
}else{
db.open();
}
}
//