前言
在我们开发的过程中,会遇到各种各样的客户,当软件开发完成后,那么就会给客户进行试用,如果你的程序不带远程锁软件功能,那么就会有客户一直白嫖,除了远程锁软件,还有加密狗,license等方法可以进行限制,加密狗的方法是安全,但总不能每个试用的客户都给他发一个加密狗吧,还有license,这种方法也挺方便的,就是比如试用30天,那么你给他一个30天左右的license,但是这个在于生成的激活文件在本地,用户只需要更改本地时间就可跳过它,而使用远程锁定软件只需要在程序内加入一段代码即可实现,前提是用户必须联网才可试用(现在大部分电脑肯定是都要联网的,少部分专用机器可能不连接互联网)
实现
在qt内想要实现这个功能很简单,只需使用QWebSocket及QWebSocketServer即可实现
就是一个服务端代码,一个客户端代码,我需要给定客户一个账号,可以给定日期,只要我服务端一直开着,那么客户每次使用软件就需要输入用户名密码,如果设置的日期到了,那么客户端那一边就无论如何都无法进行登陆
客户端代码:
.h
class ClientSocket : public QObject
{
Q_OBJECT
public:
explicit ClientSocket(QObject *parent = nullptr);
~ClientSocket();
void ConnectServer();
void DisconnectServer();
public slots:
void sendMessageToServer(QString i_text);
signals:
void sSendReceiverMessage(QString);
void sSendConnectServer(bool);
protected slots:
void onConnectServer(); //连接服务端
void onDisConnectServer(); //断开连接
void onReceiverData(const QString &msg); //接受数据。可以是json。使用qbytearray进行转化和解码
private:
QWebSocket *m_pReceiverSocket=nullptr;
};
.cpp
#include "clientsocket.h"
ClientSocket::ClientSocket(QObject *parent)
: QObject{parent}
{
m_pReceiverSocket=new QWebSocket;
m_pReceiverSocket->setParent(this);
connect(m_pReceiverSocket,&QWebSocket::connected,this,&ClientSocket::onConnectServer);
connect(m_pReceiverSocket,&QWebSocket::disconnected,this,&ClientSocket::onDisConnectServer);
connect(m_pReceiverSocket,&QWebSocket::textMessageReceived,this,&ClientSocket::onReceiverData);
}
ClientSocket::~ClientSocket()
{
}
void ClientSocket::ConnectServer()
{
m_pReceiverSocket->open(QUrl("ws://192.168.1.14:2024")); /* ws://localhost:2022 */
}
void ClientSocket::DisconnectServer()
{
m_pReceiverSocket->close();
}
void ClientSocket::sendMessageToServer(QString i_text)
{
m_pReceiverSocket->sendTextMessage(i_text);
}
void ClientSocket::onConnectServer()
{
qDebug()<<"Connet To Server";
emit sSendConnectServer(true);
}
void ClientSocket::onDisConnectServer()
{
qDebug()<<"DisConnet To Server";
emit sSendConnectServer(false);
}
void ClientSocket::onReceiverData(const QString &msg)
{
emit sSendReceiverMessage(msg);
qDebug()<<"msg = "<<msg;
}
服务端代码
.h
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void Init();
void Connect();
signals:
void sendMessage(QString);
protected slots:
void onListenClicked(); //监听事件触发
void onNewConnection(); //有新的连接加入
private:
void ClearClient(); //清除所有连接
void createSqlDatabase();
void connectSqlDatabase();
void classfiy(QString i_text);
QString createTable(QString i_sql);
void insertTable(int i_type,QString i_text);
void updateTable(int i_type,QString i_text);
void deleteTable(int i_type,QString i_text);
void selectTable(int i_type,QString i_text);
private:
QLineEdit *m_pAddressEdit=nullptr;
QLineEdit *m_pPortEdit=nullptr;
QTextEdit *m_pTextEdit=nullptr;
QPushButton *m_pConnectBtn=nullptr;
QPushButton *m_pSendBtn=nullptr;
QWebSocketServer *m_pServerSocket=nullptr;
QVector<QWebSocket *>ClientList;
TableType m_tableType=None;
QSqlDatabase m_db;
};
.cpp
#include "widget.h"
#include <QHBoxLayout>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
Init();
Connect();
//createSqlDatabase();
}
Widget::~Widget()
{
//这里是重点。一定要在析构函数中对server进行关闭。不然程序会奔溃
ClearClient();
m_pServerSocket->close();
}
void Widget::Init()
{
m_pAddressEdit=new QLineEdit(this);
m_pPortEdit=new QLineEdit(this);
m_pTextEdit=new QTextEdit(this);
m_pConnectBtn=new QPushButton(tr("Listen"),this);
m_pSendBtn=new QPushButton(tr("Send"),this);
m_pAddressEdit->setFixedSize(230,27);
m_pPortEdit->setFixedSize(100,27);
m_pConnectBtn->setFixedSize(150,27);
m_pSendBtn->setFixedSize(150,27);
m_pAddressEdit->setText("192.168.1.14");
m_pPortEdit->setText("2024");
QWidget *titleWgt=new QWidget(this);
QHBoxLayout *titleLayout=new QHBoxLayout(this);
titleLayout->addWidget(m_pAddressEdit);
titleLayout->addWidget(m_pPortEdit);
titleLayout->addWidget(m_pConnectBtn);
titleLayout->addWidget(m_pSendBtn);
titleLayout->setMargin(10);
titleLayout->setSpacing(10);
titleWgt->setLayout(titleLayout);
QVBoxLayout *mainLayout=new QVBoxLayout(this);
mainLayout->addWidget(titleWgt);
mainLayout->addWidget(m_pTextEdit);
mainLayout->setMargin(0);
mainLayout->setSpacing(0);
this->setLayout(mainLayout);
m_pSendBtn->setEnabled(false);
//server Listen
m_pServerSocket=new QWebSocketServer("Server",QWebSocketServer::NonSecureMode,this);
m_pSendBtn->setEnabled(false);
//createSqlDatabase();
// connectSqlDatabase();
// QSqlQuery m_qurey(m_db);
// m_qurey.prepare("INSERT INTO User (username, password,power) VALUES (:username, :password,:power)");
// m_qurey.bindValue(":username","admin");
// m_qurey.bindValue(":password","123456");
// m_qurey.bindValue(":power","admin");
// if (!m_qurey.exec()) {
// qDebug() << "Failed to insert inventory item";
// return;
// }
}
void Widget::Connect()
{
connect(m_pConnectBtn,&QPushButton::clicked,this,&Widget::onListenClicked);
connect(m_pServerSocket,&QWebSocketServer::newConnection,this,&Widget::onNewConnection);
connect(m_pSendBtn,&QPushButton::clicked,[this](){
if(!m_pTextEdit->toPlainText().isEmpty())
emit sendMessage(m_pTextEdit->toPlainText());
});
}
void Widget::onListenClicked()
{
if(m_pConnectBtn->text()!="Listen")
{
m_pSendBtn->setEnabled(false);
m_pConnectBtn->setText("Listen");
m_pServerSocket->close();
ClearClient();
}
else
{
QHostAddress address;
if(m_pAddressEdit->text()=="Any") //可进行监听任意地址
{
address=QHostAddress::Any;
}
else
{
address=QHostAddress(m_pAddressEdit->text()); //监听指定地址
}
if(m_pServerSocket->listen(address,m_pPortEdit->text().toUInt())){
m_pSendBtn->setEnabled(true); //成功监听。
m_pConnectBtn->setText("Dislisten");
}
}
}
void Widget::onNewConnection()
{
//监听只能监听一个ip地址。不能同时监听多个
QWebSocket *socket=m_pServerSocket->nextPendingConnection();
if(!socket)
return;
m_pTextEdit->append(QString("[new Connect] Address:%1 prot:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort()));
ClientList.push_back(socket);
connect(socket,&QWebSocket::textMessageReceived,[this](const QString &msg){
//TODO 加锁
connectSqlDatabase();
classfiy(msg);
m_db.close(); //对数据库操作完成后断开与数据库的连接
//m_pTextEdit->append(msg);
});
connect(this,&Widget::sendMessage,socket,&QWebSocket::sendTextMessage);
connect(socket,&QWebSocket::disconnected,[this,socket](){
ClientList.removeAll(socket);
socket->deleteLater();
});
}
void Widget::ClearClient()
{
for(int i=0;i<ClientList.size();++i)
{
ClientList[i]->disconnect();
ClientList[i]->close();
}
ClientList.clear();
}
void Widget::createSqlDatabase()
{
connectSqlDatabase();
QString qurey_sql="create table User (username varchar(30),password varchar(30),power varchar(30))";
qDebug()<<createTable(qurey_sql);
qurey_sql="create table Product (goods varchar(30),counts int)";
qDebug()<<createTable(qurey_sql);
qurey_sql="create table ApplicationProduct (username varchar(30),goods varchar(30),counts int,Rental varchar(30),ReturnApproval varchar(30),Devicestatus varchar(30))";
qDebug()<<createTable(qurey_sql);
//qurey_sql="create table BackProduct (username varchar(30),goods varchar(30),counts int)";
//qDebug()<<createTable(qurey_sql);
qurey_sql="create table ProductManager (username varchar(30),goods varchar(30),counts int,comment varchar(100))";
qurey_sql="create table License (username varchar(30),goods varchar(30),counts int,comment varchar(100))"; //lincese申请表
qDebug()<<createTable(qurey_sql);
}
void Widget::connectSqlDatabase()
{
if(QSqlDatabase::contains("qt_sql_default_connection"))
{
m_db=QSqlDatabase::database("qt_sql_default_connection");
}
else
{
m_db = QSqlDatabase::addDatabase("QSQLITE");
}
m_db.setDatabaseName("inventory.db");
if (!m_db.open()) {
qDebug() << "Failed to open database";
return;
}
}
void Widget::classfiy(QString i_text)
{
QStringList strList=i_text.split("_");
if(strList.size()>=2)
{
int i_tableType=strList[0].toInt();
int i_sqltype=strList[1].toInt();
switch (i_sqltype) {
case INSERT:
insertTable(i_tableType,i_text);
break;
case UPDATE:
updateTable(i_tableType,i_text);
break;
case DELETE:
deleteTable(i_tableType,i_text);
break;
case SELECT:
selectTable(i_tableType,i_text);
break;
default:
break;
}
}
}
QString Widget::createTable(QString i_sql)
{
QSqlQuery qurey(m_db);
QString qurey_sql=i_sql;
qurey.prepare(qurey_sql);
if(!qurey.exec())
{
qDebug() << "Error: Fail to create table." << qurey.lastError();
return QString("Error: Fail to create table.");
}
return QString("Table created!");
}
void Widget::insertTable(int i_type, QString i_text)
{
switch (i_type) {
case USER:
{
QStringList strList=i_text.split("_");
if(strList.size()==5)
{
QString struserName=strList[2];
QString strpassword=strList[3];
QString strpower=strList[4];
QSqlQuery m_qurey(m_db);
m_qurey.prepare("INSERT INTO User (username, password,power) VALUES (:username, :password,:power)");
m_qurey.bindValue(":username",struserName);
m_qurey.bindValue(":password",strpassword);
m_qurey.bindValue(":power",strpower);
bool isInsert=true;
if (!m_qurey.exec()) {
qDebug() << "Failed to insert inventory item";
isInsert=false;
}
QJsonArray array;
array.append(isInsert);
QJsonObject jsonObj;
jsonObj.insert(QString::number(TableType::USER)+"_"+QString::number(SqlType::INSERT),array);
QJsonDocument jsonDoc(jsonObj);
QString jsonString = jsonDoc.toJson();
emit sendMessage(jsonString);
}
}
break;
case PRODUCT:
{
QStringList strList=i_text.split("_");
if(strList.size()==4)
{
QString strproduct=strList[2];
QString strCount=strList[3];
QSqlQuery m_qurey(m_db);
m_qurey.prepare("INSERT INTO Product (goods, counts) VALUES (:goods, :counts)");
m_qurey.bindValue(":goods",strproduct);
m_qurey.bindValue(":counts",strCount);
bool isInsert=true;
if (!m_qurey.exec()) {
qDebug() << "Failed to insert inventory item";
isInsert=false;
}
QJsonArray array;
array.append(isInsert);
QJsonObject jsonObj;
jsonObj.insert(QString::number(TableType::PRODUCT)+"_"+QString::number(SqlType::INSERT),array);
QJsonDocument jsonDoc(jsonObj);
QString jsonString = jsonDoc.toJson();
emit sendMessage(jsonString);
}
}
break;
case APPLICATIONPRODUCT:
break;
case BACKPRODUCT:
break;
case PRODUCTMANAGER:
break;
default:
break;
}
}
void Widget::updateTable(int i_type, QString i_text)
{
switch (i_type) {
case USER:
{
QStringList strList=i_text.split("_");
QSqlQuery m_qurey(m_db);
bool isUpdate=false;
QString s_username=strList[2];
QString s_password=strList[3];
QString updatesql="UPDATE User SET password = :newPassword WHERE username = :username";
m_qurey.prepare(updatesql);
m_qurey.bindValue(":newPassword",s_password);
m_qurey.bindValue(":username",s_username);
if (!m_qurey.exec()) {
qDebug() << "Error updating data:" << m_qurey.lastError();
} else {
isUpdate=true;
qDebug() << "Data updated!";
}
QJsonArray array;
array.append(isUpdate);
QJsonObject jsonObj;
jsonObj.insert(QString::number(TableType::USER)+"_"+QString::number(SqlType::UPDATE),array);
QJsonDocument jsonDoc(jsonObj);
QString jsonString = jsonDoc.toJson();
emit sendMessage(jsonString);
}
break;
case PRODUCT:
{
QStringList strList=i_text.split("_");
QSqlQuery m_qurey(m_db);
bool isUpdate=false;
QString s_name=strList[2];
int iAddCount=strList[3].toInt();
QString strOperator=strList[4];
//先查找
m_qurey.prepare("SELECT counts FROM Product WHERE goods = :goods");
m_qurey.bindValue(":goods", s_name);
if (!m_qurey.exec()) {
qDebug() << "Error: Failed to execute query." << m_qurey.lastError();
return;
}
if (m_qurey.next()) {
int count = m_qurey.value(0).toInt();
if(strOperator=="+")
{
iAddCount+=count;
}
else
{
iAddCount=count-iAddCount;
}
}
QString updatesql="UPDATE Product SET counts = :newCounts WHERE goods = :goods";
m_qurey.prepare(updatesql);
m_qurey.bindValue(":newCounts",iAddCount);
m_qurey.bindValue(":goods",s_name);
if (!m_qurey.exec()) {
qDebug() << "Error updating data:" << m_qurey.lastError();
} else {
isUpdate=true;
qDebug() << "Data updated!";
}
if(strList.size()==8)
{
QString strInstruct=strList[5];
QString strBuy=strList[6];
QString strExam=strList[7];
//QSqlQuery m_qurey(m_db);
m_qurey.prepare("INSERT INTO ApplicationProduct (username, goods,counts,Rental,ReturnApproval,Devicestatus) VALUES (:username, :goods,:counts,:Rental,:ReturnApproval,:Devicestatus)");
m_qurey.bindValue(":username",strBuy);
m_qurey.bindValue(":goods",s_name);
m_qurey.bindValue(":counts",strList[3]);
m_qurey.bindValue(":Rental",strExam);
m_qurey.bindValue(":ReturnApproval","");
m_qurey.bindValue(":Devicestatus",strInstruct);
if (!m_qurey.exec()) {
qDebug() << "Failed to insert inventory item";
}
}
QJsonArray array;
array.append(isUpdate);
QJsonObject jsonObj;
jsonObj.insert(QString::number(TableType::PRODUCT)+"_"+QString::number(SqlType::UPDATE),array);
QJsonDocument jsonDoc(jsonObj);
QString jsonString = jsonDoc.toJson();
emit sendMessage(jsonString);
}
break;
case APPLICATIONPRODUCT:
break;
case BACKPRODUCT:
break;
case PRODUCTMANAGER:
break;
default:
break;
}
}
void Widget::deleteTable(int i_type, QString i_text)
{
switch (i_type) {
case USER:
{
QStringList strList=i_text.split("_");
QSqlQuery m_qurey(m_db);
bool isDelete=false;
for(int i=2;i<strList.size();++i)
{
QString deletesql="DELETE FROM User WHERE username = :username";
m_qurey.prepare(deletesql);
m_qurey.bindValue(":username",strList[i]);
if(!m_qurey.exec())
{
qDebug()<<m_qurey.lastError();
}
else
{
isDelete=true;
qDebug()<<"deleted!";
}
}
QJsonArray array;
array.append(isDelete);
QJsonObject jsonObj;
jsonObj.insert(QString::number(TableType::USER)+"_"+QString::number(SqlType::DELETE),array);
QJsonDocument jsonDoc(jsonObj);
QString jsonString = jsonDoc.toJson();
emit sendMessage(jsonString);
}
break;
case PRODUCT:
{
QStringList strList=i_text.split("_");
QSqlQuery m_qurey(m_db);
bool isDelete=false;
for(int i=2;i<strList.size();++i)
{
QString deletesql="DELETE FROM Product WHERE goods = :goods";
m_qurey.prepare(deletesql);
m_qurey.bindValue(":goods",strList[i]);
if(!m_qurey.exec())
{
qDebug()<<m_qurey.lastError();
}
else
{
isDelete=true;
qDebug()<<"deleted!";
}
}
QJsonArray array;
array.append(isDelete);
QJsonObject jsonObj;
jsonObj.insert(QString::number(TableType::PRODUCT)+"_"+QString::number(SqlType::DELETE),array);
QJsonDocument jsonDoc(jsonObj);
QString jsonString = jsonDoc.toJson();
emit sendMessage(jsonString);
}
break;
case APPLICATIONPRODUCT:
break;
case BACKPRODUCT:
break;
case PRODUCTMANAGER:
break;
default:
break;
}
}
void Widget::selectTable(int i_type, QString i_text)
{
switch (i_type) {
case USER:
{
QStringList strList=i_text.split("_");
QString strusername="",strpassword="";
if(strList.size()==4)
{
strusername=strList[2];
strpassword=strList[3];
}
QString selectAll="select * from User";
QSqlQuery m_qurey(m_db);
m_qurey.prepare(selectAll);
m_qurey.exec();
QJsonObject jsonObj;
QJsonArray jsonArray;
while(m_qurey.next())
{
QString username = m_qurey.value(0).toString();
QString password = m_qurey.value(1).toString();
if(strusername==username&&strpassword==password)
{
m_pTextEdit->append(QString("%1登录了系统").arg(username));
}
QString power = m_qurey.value(2).toString();
QString strGroup=username+"_"+password+"_"+power;
jsonArray.append(strGroup);
}
jsonObj.insert(QString::number(TableType::USER)+"_"+QString::number(SqlType::SELECT),jsonArray);
QJsonDocument jsonDoc(jsonObj);
QString jsonString = jsonDoc.toJson();
emit sendMessage(jsonString);
}
break;
case PRODUCT:
{
QStringList strList=i_text.split("_");
QString selectAll="select * from Product";
QSqlQuery m_qurey(m_db);
m_qurey.prepare(selectAll);
m_qurey.exec();
QJsonObject jsonObj;
QJsonArray jsonArray;
while(m_qurey.next())
{
QString product = m_qurey.value(0).toString();
QString counts = m_qurey.value(1).toString();
QString strGroup=product+"_"+counts;
jsonArray.append(strGroup);
}
jsonObj.insert(QString::number(TableType::PRODUCT)+"_"+QString::number(SqlType::SELECT),jsonArray);
QJsonDocument jsonDoc(jsonObj);
QString jsonString = jsonDoc.toJson();
emit sendMessage(jsonString);
}
break;
case APPLICATIONPRODUCT:
{
QString selectAll="select * from ApplicationProduct";
QSqlQuery m_qurey(m_db);
m_qurey.prepare(selectAll);
m_qurey.exec();
QJsonObject jsonObj;
QJsonArray jsonArray;
while(m_qurey.next())
{
QString username = m_qurey.value(0).toString();
QString goods = m_qurey.value(1).toString();
QString counts = m_qurey.value(2).toString();
QString Rental = m_qurey.value(3).toString();
QString ReturnApproval = m_qurey.value(4).toString();
QString Devicestatus = m_qurey.value(5).toString();
QString strGroup=username+"_"+goods+"_"+counts+"_"+Rental+"_"+ReturnApproval+"_"+Devicestatus;
jsonArray.append(strGroup);
}
jsonObj.insert(QString::number(TableType::APPLICATIONPRODUCT)+"_"+QString::number(SqlType::SELECT),jsonArray);
QJsonDocument jsonDoc(jsonObj);
QString jsonString = jsonDoc.toJson();
emit sendMessage(jsonString);
}
break;
case BACKPRODUCT:
break;
case PRODUCTMANAGER:
break;
default:
break;
}
}
我做的是一个仓库管理的系统,用到了数据库,所以服务端我直接粘贴的所有代码,
效果如下