commit 2992ccd00dc49143c5c2a81bd8ff78fb6ca98349 Author: Msy-msu <2200456405@qq.com> Date: Thu Jan 5 19:50:19 2023 +0800 first commit diff --git a/TcpServer.pro b/TcpServer.pro new file mode 100644 index 0000000..445e20d --- /dev/null +++ b/TcpServer.pro @@ -0,0 +1,27 @@ +QT += core gui network sql + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++11 + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + database.cpp \ + datamanager.cpp \ + main.cpp \ + protocol.cpp \ + tcpserver.cpp + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +HEADERS += \ + database.h \ + datamanager.h \ + protocol.h \ + tcpserver.h diff --git a/TcpServer.pro.user b/TcpServer.pro.user new file mode 100644 index 0000000..93f1308 --- /dev/null +++ b/TcpServer.pro.user @@ -0,0 +1,430 @@ + + + + + + EnvironmentId + {d3fed20c-1c94-44fc-8f6a-4dbf39b54775} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + false + true + false + 0 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + + 0 + true + + -fno-delayed-template-parsing + + true + Builtin.BuildSystem + + true + true + Builtin.DefaultTidyAndClazy + 4 + + + + true + + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop Qt 6.2.3 MSVC2019 64bit + Desktop Qt 6.2.3 MSVC2019 64bit + qt.qt6.623.win64_msvc2019_64_kit + 0 + 0 + 0 + + 0 + C:\Users\25761\Desktop\build-TcpServer-Desktop_Qt_6_2_3_MSVC2019_64bit-Debug + C:/Users/25761/Desktop/build-TcpServer-Desktop_Qt_6_2_3_MSVC2019_64bit-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + C:\Users\25761\Desktop\build-TcpServer-Desktop_Qt_6_2_3_MSVC2019_64bit-Release + C:/Users/25761/Desktop/build-TcpServer-Desktop_Qt_6_2_3_MSVC2019_64bit-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + C:\Users\25761\Desktop\build-TcpServer-Desktop_Qt_6_2_3_MSVC2019_64bit-Profile + C:/Users/25761/Desktop/build-TcpServer-Desktop_Qt_6_2_3_MSVC2019_64bit-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + true + + 2 + + Qt4ProjectManager.Qt4RunConfiguration:C:/Users/25761/Desktop/TcpServer/TcpServer.pro + C:/Users/25761/Desktop/TcpServer/TcpServer.pro + false + true + true + false + true + C:/Users/25761/Desktop/build-TcpServer-Desktop_Qt_6_2_3_MSVC2019_64bit-Debug + + 1 + + + + ProjectExplorer.Project.Target.1 + + Desktop + Desktop Qt 6.2.3 MinGW 64-bit + Desktop Qt 6.2.3 MinGW 64-bit + qt.qt6.623.win64_mingw_kit + 0 + 0 + 0 + + 0 + C:\Users\25761\Desktop\build-TcpServer-Desktop_Qt_6_2_3_MinGW_64_bit-Debug + C:/Users/25761/Desktop/build-TcpServer-Desktop_Qt_6_2_3_MinGW_64_bit-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + C:\Users\25761\Desktop\build-TcpServer-Desktop_Qt_6_2_3_MinGW_64_bit-Release + C:/Users/25761/Desktop/build-TcpServer-Desktop_Qt_6_2_3_MinGW_64_bit-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + C:\Users\25761\Desktop\build-TcpServer-Desktop_Qt_6_2_3_MinGW_64_bit-Profile + C:/Users/25761/Desktop/build-TcpServer-Desktop_Qt_6_2_3_MinGW_64_bit-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + 1 + + true + true + true + + 2 + + ProjectExplorer.CustomExecutableRunConfiguration + + false + true + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 2 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/database.cpp b/database.cpp new file mode 100644 index 0000000..48ebb76 --- /dev/null +++ b/database.cpp @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include +#include "database.h" + +DataBase *DataBase::getInstance() +{ + static DataBase sqldb; + return &sqldb; +} + +DataBase::DataBase() +{ + //先判断连接是否存在 + if(QSqlDatabase::contains("testConnection")) + { + db_ = QSqlDatabase::addDatabase("testConnection"); + } + else + { + //1.加载数据库驱动 + db_ = QSqlDatabase::addDatabase("QSQLITE", "testConnection"); + qDebug () << db_.connectionName();//打印连接名称 + + //2.设置数据库名 + db_.setDatabaseName("usr.db"); + qDebug () << db_.databaseName(); + } + + //3.打开数据库 + if(db_.open()) + { + qDebug() << "open success"; + } + else + { + qDebug() << "open:" << db_.lastError().text(); + return; + } + + QString sql = "create table if not exists table_usr(name varchar(30) primary key, pwd varchar(20));"; + QSqlQuery query(db_); + if (query.exec(sql)) + { + qDebug() << "create success."; + } + db_.close(); +} + + +//插入一个用户信息 +bool DataBase::insertUsr(QString name, QString pwd) +{ + QString sql = QString("insert into table_usr values('%1', '%2')") + .arg(name) + .arg(pwd); + + + // 1.打开数据 + if (!db_.open()) + { + qDebug() << "open:" << db_.lastError().text(); + return false; + } + + // 2.执行sql + QSqlQuery query(db_); + if (!query.exec(sql)) + { + qDebug() << "insert:" << query.lastError().text(); + return false; + } + + //关闭数据库 + db_.close(); + return true; + +} + + +//根据name查找用户 +bool DataBase::findUsr(QString name) +{ + QString sql = QString(" from table_usr where name = :name;"); + //打开数据库 + if(!db_.open()) + { + qDebug() << "open fail" << db_.lastError().text(); + exit(-1); + } + + //执行插入操作 + QSqlQuery query(db_); + query.prepare(sql); + query.bindValue(":name",QVariant(name)); + query.exec(); + + //查询成功 + if(query.next()) + { + if(name == query.value(0).toString()) //用户存在 + { + return true; + } + } + + db_.close(); + return false; +} + +bool DataBase::Delete(QString name) +{ + QString sql = QString("select name from table_usr where name = :name;"); + //打开数据库 + if(!db_.open()) + { + qDebug() << "open fail" << db_.lastError().text(); + exit(-1); + } + + //执行删除操作 + QSqlQuery query(db_); + + if (!query.exec(sql)) + { + qDebug() << "delete" << query.lastError().text(); + return false; + } + + //关闭数据库 + db_.close(); + return true; +} + +//匹配name和pwd +bool DataBase::match(QString name, QString pwd) +{ + QString sql = QString("select name, pwd from table_usr where name = :name;"); + //打开数据库 + if(!db_.open()) + { + qDebug() << "open fail" << db_.lastError().text(); + exit(-1); + } + + //执行插入操作 + QSqlQuery query(db_); + query.prepare(sql); + query.bindValue(":name",QVariant(name)); + query.exec(); + + //匹配密码 + if(query.next()) + { + if(!(pwd == query.value(1).toString())) + { + return false; + } + } + + //关闭数据库 + db_.close(); + + return true; +} + diff --git a/database.h b/database.h new file mode 100644 index 0000000..9629b4e --- /dev/null +++ b/database.h @@ -0,0 +1,32 @@ +#ifndef DATABASE_H +#define DATABASE_H +#include +#include +#include +#include +#include + +class DataBase +{ +public: + static DataBase *getInstance(); //静态的获取数据库对象的函数 + + //插入一个用户信息 + bool insertUsr(QString name,QString pwd); + + //根据name查找用户 + bool findUsr(QString name); + + //匹配name和pwd + bool match(QString name, QString pwd); + + //删除用户信息 + bool Delete(QString name); + + DataBase(); + + QSqlDatabase db_; +}; + +#endif // DATABASE_H + diff --git a/datamanager.cpp b/datamanager.cpp new file mode 100644 index 0000000..c81d9f8 --- /dev/null +++ b/datamanager.cpp @@ -0,0 +1,23 @@ +#include "datamanager.h" + +DataManager::DataManager(QObject *parent) + : QObject{parent} +{ + database = DataBase::getInstance(); + protocol = Protocol::getInstance(); + server = TCPServer::getInstance(); + server->configAndrun(); + server->setCallBack(disconnect_from_cln); + server->setCallBack(recv_from_cln); + +} + +void DataManager::disconnect_from_cln(QTcpSocket *sock) +{ + +} + +void DataManager::recv_from_cln(QByteArray &data, QTcpSocket *sock) +{ + +} diff --git a/datamanager.h b/datamanager.h new file mode 100644 index 0000000..6ad3a41 --- /dev/null +++ b/datamanager.h @@ -0,0 +1,28 @@ +#ifndef DATAMANAGER_H +#define DATAMANAGER_H + +#include + +#include "database.h" +#include "tcpserver.h" +#include "protocol.h" + +class DataManager : public QObject +{ + Q_OBJECT +public: + explicit DataManager(QObject *parent = nullptr); + static void disconnect_from_cln(QTcpSocket* sock); + static void recv_from_cln(QByteArray &data, QTcpSocket* sock); + +signals: + +private: + DataBase *database; + Protocol *protocol; + TCPServer *server; + QList online_socket_list; + QList online_name_list; +}; + +#endif // DATAMANAGER_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..05eaa16 --- /dev/null +++ b/main.cpp @@ -0,0 +1,10 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + DataManager datamanager; + return a.exec(); +} diff --git a/protocol.cpp b/protocol.cpp new file mode 100644 index 0000000..98db9b4 --- /dev/null +++ b/protocol.cpp @@ -0,0 +1,152 @@ +#include "protocol.h" +#include +#include + +Protocol Protocol::protocol_instance; +Protocol::Protocol(QObject *parent) + : QObject{parent} +{ + +} + +Protocol::~Protocol() +{ + +} + +Protocol* Protocol::getInstance() +{ + return &protocol_instance; +} + +QByteArray Protocol::data_builder(QList &args) +{ + QJsonObject data; + switch(args[0].get_data_types()) + { + case MESSAGE: + { + if (args.length()==2) + { + data.insert("type","message"); + data.insert("data",args[1].get_string()); + } + else if (args.length()==3) + { + data.insert("type","message"); + data.insert("to_user",args[1].get_string()); + data.insert("data",args[2].get_string()); + } + break; + } + case FILE: + { + data.insert("type","file"); + data.insert("name",args[1].get_string()); + data.insert("data",args[2].get_string()); + break; + } + case REQUEST: + { + data.insert("type","request"); + data.insert("action",args[1].get_string()); + QList content = args[2].get_list(); + QJsonObject json_content; + for (int i=0; i users = args[2].get_list(); + QJsonArray json_users; + for (auto &user:users) + json_users.append(user); + data.insert("users",json_users); + break; + } + case RESPONSE: + { + data.insert("type","response"); + data.insert("action",args[1].get_string()); + QList content = args[2].get_list(); + QJsonObject json_content; + for (int i=0; i Protocol::data_parser(QByteArray data) +{ + QJsonDocument json_data = QJsonDocument::fromJson(data); + if (json_data["type"] == "message") + return qMakePair(MESSAGE,json_data.object()); + else if (json_data["type"] == "file") + return qMakePair(FILE,json_data.object()); + else if (json_data["type"] == "request") + return qMakePair(REQUEST,json_data.object()); + else if (json_data["type"] == "online_users") + return qMakePair(ONLINEUSERS,json_data.object()); + else if (json_data["type"] == "response") + return qMakePair(RESPONSE,json_data.object()); + else + return qMakePair(RESPONSE,json_data.object()); +} + +QByteArray Protocol::XOR_En_Decrypt(QString src) +{ + QByteArray result; + for(auto &i:src) + result.append(i.toLatin1() ^ cipher_word); + return result; +} + +QByteArray Protocol::Upper_Lower_En_Decrypt(QString src) +{ + QByteArray result; + for(auto &i:src) + { + if(i.isUpper()) + { + QChar word = i.toLower(); + result.append(word.toLatin1()); + } + else if (i.isLower()) + { + QChar word = i.toUpper(); + result.append(word.toLatin1()); + } + else + result.append(i.toLatin1()); + } + return result; +} + +QByteArray Protocol::data_encrypt(QByteArray src) +{ + QByteArray en_base64 = src.toBase64(); + QByteArray result = Upper_Lower_En_Decrypt(en_base64); + return XOR_En_Decrypt(result); +} + +QByteArray Protocol::data_decrypt(QByteArray src) +{ + QByteArray result = XOR_En_Decrypt(src); + result = Upper_Lower_En_Decrypt(result); + return QByteArray::fromBase64(result); +} + +void Protocol::set_data_cipher_word(char word) +{ + cipher_word = word; +} diff --git a/protocol.h b/protocol.h new file mode 100644 index 0000000..b6ccef1 --- /dev/null +++ b/protocol.h @@ -0,0 +1,60 @@ +#ifndef PROTOCOL_H +#define PROTOCOL_H + +#include +#include + +class Protocol : public QObject +{ + Q_OBJECT +public: + static Protocol* getInstance(); + template + QByteArray data_maker(Type type, Args ...args) + { + QList args_list; + args_list.append(any_types(type)); + (void)std::initializer_list {(args_list.append(any_types(args)),0)...}; + return data_builder(args_list); + }; + enum data_types {MESSAGE,FILE,REQUEST,ONLINEUSERS,RESPONSE}; + QPair data_parser(QByteArray data); + QByteArray data_encrypt(QByteArray src); + void set_data_cipher_word(char word); + QByteArray data_decrypt(QByteArray src); +private: + char cipher_word = 'G'; + struct any_types { + enum type {String, Bool, Int, Data_types, List}; + any_types(int e) { m_data.INT = e; m_type = Int;} + any_types(QString e) { m_data.STRING = e; m_type = String;} + any_types(QList e) { m_data.LIST = e; m_type = List;} + any_types(bool e) { m_data.BOOL = e; m_type = Bool;} + any_types(data_types e) { m_data.DATA_TYPES = e; m_type = Data_types;} + type get_type() const { return m_type; } + int get_int() const { return m_data.INT; } + bool get_bool() const { return m_data.BOOL; } + data_types get_data_types() const { return m_data.DATA_TYPES; } + QString get_string() const { return m_data.STRING; } + QList get_list() const { return m_data.LIST; } + private: + type m_type; + struct { + int INT; + bool BOOL; + QString STRING; + QList LIST; + data_types DATA_TYPES; + } m_data; + }; + static Protocol protocol_instance; + explicit Protocol(QObject *parent = nullptr); + ~Protocol(); + QByteArray data_builder(QList &args); + QByteArray XOR_En_Decrypt(QString src); + QByteArray Upper_Lower_En_Decrypt(QString src); +signals: + +}; +#endif // PROTOCOL_H + diff --git a/tcpserver.cpp b/tcpserver.cpp new file mode 100644 index 0000000..eeca19a --- /dev/null +++ b/tcpserver.cpp @@ -0,0 +1,124 @@ +#include "tcpserver.h" + +using namespace std; + +TCPServer TCPServer::tcpserver_instance; + +TCPServer::TCPServer(QObject *parent) + : QObject{parent} +{ + +} + +TCPServer::~TCPServer() +{ + +} + +TCPServer* TCPServer::getInstance() +{ + return &tcpserver_instance; +} + +void TCPServer::configAndrun() +{ + tcp_server.listen(QHostAddress(listen_addr), listen_port); + connect(&tcp_server, &QTcpServer::newConnection, this, &TCPServer::acceptTCPConnection); + QByteArray addr = listen_addr.toLocal8Bit(); + qDebug() << "successfully start server"; + printf("TCP Server Started at %.*s:%d.\n", addr.length(), addr.data(),listen_port); +} + +void TCPServer::setServer(QString IP, qint16 port) +{ + listen_addr = IP; + listen_port = port; +} + +void TCPServer::stopRun() +{ + tcp_server.close(); + QByteArray addr = listen_addr.toLocal8Bit(); + printf("TCP Server Closed at %.*s:%d.\n",addr.length(), addr.data(),listen_port); +} + +void TCPServer::acceptTCPConnection() +{ + QTcpSocket* clientConnection = tcp_server.nextPendingConnection(); + if(clientConnection!=nullptr) + { + qDebug() << "new conncection"; + clientConnection->setParent(this); + tcp_socket_list.append(clientConnection); + connect(clientConnection, &QTcpSocket::readyRead, this, &TCPServer::TCPReadPeer); + connect(clientConnection,&QTcpSocket::disconnected,this,&TCPServer::discTCPConnection); + QString ip = clientConnection->peerAddress().toString(); + string ip_t = ip.toStdString(); + printf("TCP: %.*s:%d connected.\n",ip_t.length(), ip_t.data(), clientConnection->peerPort()); + } +} + +void TCPServer::discTCPConnection() +{ + for (int i=0;i(sender()))//可以直接用sender()解决,此处为稳健起见还是采取遍历 + { + QString ip = tcp_socket_list[i]->peerAddress().toString(); + string ip_t = ip.toStdString(); + printf("TCP: %.*s:%d Disconnected.\n",ip_t.length(), ip_t.data(), tcp_socket_list[i]->peerPort()); + if (disccallback != nullptr) + disccallback(tcp_socket_list[i]); + tcp_socket_list.removeAt(i); + dynamic_cast(sender())->deleteLater(); + qDebug() << "disconnect"; + break; + } + } +} + +void TCPServer::TCPReadPeer() +{ + sock =(QTcpSocket *)sender(); + QByteArray recv; + while(sock->bytesAvailable())//循环接收 + { + recv += sock->readAll(); + if (!sock->waitForReadyRead(20))//超时停止接收 + { + /*QString error = sock->errorString(); + string error_t = error.toStdString(); + log_w("error:%d: %.*s", sock->error(),error_t.length(), error_t.data());*/ + break; + } + } + QString ip = sock->peerAddress().toString(); + string ip_t = ip.toStdString(); + printf("TCPC: Recvd from %.*s:%d\n", ip_t.length(), ip_t.data(), sock->peerPort()); + printf("TCP Message:%.*s\n",recv.size(),(char *)recv.data()); + if (recvcallback != nullptr) + recvcallback(recv,sock); +} + +void TCPServer::setCallBack(void (*callback)(QByteArray &data, QTcpSocket* socket)) +{ + recvcallback = callback; +} + +void TCPServer::setCallBack(void (*callback)(QTcpSocket* socket)) +{ + disccallback = callback; +} + +void TCPServer::sendToclient(QString ip, quint16 port, QByteArray data) +{ + QHostAddress addr(ip); + for (int i=0;ipeerAddress()&&tcp_socket_list[i]->peerPort()==port) + { + tcp_socket_list[i]->write(data); + break; + } + } +} diff --git a/tcpserver.h b/tcpserver.h new file mode 100644 index 0000000..6c2be3d --- /dev/null +++ b/tcpserver.h @@ -0,0 +1,38 @@ +#ifndef TCPSERVER_H +#define TCPSERVER_H + +#include +#include +#include +#include + +class TCPServer : public QObject +{ + Q_OBJECT +public: + static TCPServer* getInstance(); + void configAndrun(); + void setServer(QString IP, qint16 port); + void setCallBack(void (*callback)(QByteArray &data,QTcpSocket* socket));//Qt的信号-槽机制实际就是回调函数, + void setCallBack(void (*callback)(QTcpSocket* socket)); //此处为练手,不使用该机制 + void sendToclient(QString ip, quint16 port, QByteArray data); + void stopRun(); +private: + explicit TCPServer(QObject *parent = nullptr); + ~TCPServer(); + QString listen_addr = "0.0.0.0"; + qint16 listen_port = 7890; + QTcpServer tcp_server; + QTcpSocket* sock; + QList tcp_socket_list; + void (*recvcallback) (QByteArray &data, QTcpSocket* socket)=nullptr; + void (*disccallback) (QTcpSocket* socket)=nullptr; + static TCPServer tcpserver_instance; +private slots: + void acceptTCPConnection(); + void TCPReadPeer(); + void discTCPConnection(); +signals: +}; + +#endif // TCPSERVER_H