Initial commit

This commit is contained in:
Mentalflow 2022-12-11 14:04:13 +08:00
parent cbf3d39283
commit 0abbb46040
Signed by: Mentalflow
GPG Key ID: 5AE68D4401A2EE71
11 changed files with 566 additions and 1 deletions

26
DataManager.pro Normal file
View File

@ -0,0 +1,26 @@
QT -= gui
QT += network
CONFIG += c++11 console
CONFIG -= app_bundle
# 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 += \
datamanager.cpp \
main.cpp \
protocol.cpp \
tcpclient.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 += \
datamanager.h \
protocol.h \
tcpclient.h \
tcpserver.h

View File

@ -1,2 +1,2 @@
# data_manager
一个轻量级、可拓展的基于Json的通信协议。
一个轻量级、可拓展的基于Json的通信协议(开发中)

7
datamanager.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "datamanager.h"
DataManager::DataManager(QObject *parent)
: QObject{parent}
{
}

16
datamanager.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef DATAMANAGER_H
#define DATAMANAGER_H
#include <QObject>
class DataManager : public QObject
{
Q_OBJECT
public:
explicit DataManager(QObject *parent = nullptr);
signals:
};
#endif // DATAMANAGER_H

13
main.cpp Normal file
View File

@ -0,0 +1,13 @@
#include <QCoreApplication>
#include "protocol.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Protocol *p = Protocol::getInstance();
QList<QString> users{QString("123321123"),QString("123321123"),QString("123321123"),QString("123321123")};
qDebug()<<p->data_parser(p->data_maker(Protocol::ONLINEUSERS,4,users));
qDebug()<<p->data_encrypt(p->data_maker(Protocol::ONLINEUSERS,4,users));
qDebug()<<p->data_decrypt(p->data_encrypt(p->data_maker(Protocol::ONLINEUSERS,4,users)));
return a.exec();
}

152
protocol.cpp Normal file
View File

@ -0,0 +1,152 @@
#include "protocol.h"
#include <QJsonDocument>
#include <QJsonArray>
Protocol Protocol::protocol_instance;
Protocol::Protocol(QObject *parent)
: QObject{parent}
{
}
Protocol::~Protocol()
{
}
Protocol* Protocol::getInstance()
{
return &protocol_instance;
}
QByteArray Protocol::data_builder(QList<any_types> &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<QString> content = args[2].get_list();
QJsonObject json_content;
for (int i=0; i<content.length(); i+=2)
json_content.insert(content[i],content[i+1]);
data.insert("content",json_content);
break;
}
case ONLINEUSERS:
{
data.insert("type","online_users");
data.insert("count",args[1].get_int());
QList<QString> 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<QString> content = args[2].get_list();
QJsonObject json_content;
for (int i=0; i<content.length(); i+=2)
json_content.insert(content[i],content[i+1]);
data.insert("content",json_content);
break;
}
default:
break;
}
QJsonDocument data_doc(data);
return data_doc.toJson(QJsonDocument::Compact)+'\n';
}
QPair<Protocol::data_types,QJsonObject> 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;
}

59
protocol.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef PROTOCOL_H
#define PROTOCOL_H
#include <QObject>
#include <QJsonObject>
class Protocol : public QObject
{
Q_OBJECT
public:
static Protocol* getInstance();
template<typename Type, typename ...Args>
QByteArray data_maker(Type type, Args ...args)
{
QList<any_types> args_list;
args_list.append(any_types(type));
(void)std::initializer_list <int> {(args_list.append(any_types(args)),0)...};
return data_builder(args_list);
};
enum data_types {MESSAGE,FILE,REQUEST,ONLINEUSERS,RESPONSE};
QPair<data_types,QJsonObject> 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<QString> 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<QString> get_list() const { return m_data.LIST; }
private:
type m_type;
struct {
int INT;
bool BOOL;
QString STRING;
QList<QString> LIST;
data_types DATA_TYPES;
} m_data;
};
static Protocol protocol_instance;
explicit Protocol(QObject *parent = nullptr);
~Protocol();
QByteArray data_builder(QList<any_types> &args);
QByteArray XOR_En_Decrypt(QString src);
QByteArray Upper_Lower_En_Decrypt(QString src);
signals:
};
#endif // PROTOCOL_H

96
tcpclient.cpp Normal file
View File

@ -0,0 +1,96 @@
#include "tcpclient.h"
#include <QHostAddress>
#include <QTime>
#include <QCoreApplication>
using namespace std;
TCPClient TCPClient::tcpclient_instance;
QTcpSocket TCPClient::socket;
TCPClient::TCPClient(QObject *parent)
: QObject{parent}
{
}
TCPClient::~TCPClient()
{
}
TCPClient* TCPClient::getInstance()
{
return &tcpclient_instance;
}
void TCPClient::configAndrun()
{
socket.setSocketOption(QAbstractSocket::KeepAliveOption,1);
socket.connectToHost(server_ip, server_port);
connect(&socket,&QTcpSocket::connected,this,&TCPClient::connected);
connect(&socket,&QTcpSocket::disconnected,this,&TCPClient::disconnected);
connect(&socket,&QTcpSocket::readyRead,this,&TCPClient::readSocket);
}
void TCPClient::sendToserver(QByteArray &data)
{
if (socket.isOpen())
{
socket.write(data);
socket.waitForBytesWritten(2000);
}
}
void TCPClient::setServer(QString IP, qint16 port)
{
server_ip = IP;
server_port = port;
}
void TCPClient::connected()
{
emit TCPClientConnected();
QString addr_t = socket.peerAddress().toString();
QByteArray addr = addr_t.toLocal8Bit();
printf("Connected to server at %.*s:%d.\n",addr.size(),addr.data(),socket.peerPort());
}
void TCPClient::disconnected()
{
emit TCPClientDisconnected();
printf("Disconnected from server.\n");
}
void TCPClient::readSocket()
{
QByteArray recv;
while(socket.bytesAvailable())//循环接收
{
recv += socket.readAll();
if (!socket.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 = socket.peerAddress().toString();
string ip_t = ip.toStdString();
printf("TCPC: Recvd from %.*s:%d\n", ip_t.length(), ip_t.data(), socket.peerPort());
printf("TCPC Message:%.*s\n",recv.size(),(char *)recv.data());
if (_callback != nullptr)
_callback(ip, socket.peerPort(),recv);
}
void TCPClient::setCallBack(void (*callback)(QString &mac, quint16 port, QByteArray &data))
{
_callback = callback;
}
void TCPClient::_sleep(int msec)
{
QTime dieTime = QTime::currentTime().addMSecs(msec);
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

39
tcpclient.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
class TCPClient : public QObject
{
Q_OBJECT
public:
static TCPClient* getInstance();
static void sendToserver(QByteArray &data);
void configAndrun();
void setCallBack(void (*callback)(QString &ip, quint16 port, QByteArray &data));
void setServer(QString IP, qint16 port);
private slots:
void connected();
void readSocket();
void disconnected();
private:
explicit TCPClient(QObject *parent = nullptr);
~TCPClient();
static void _sleep(int msec);
static QTcpSocket socket;
static TCPClient tcpclient_instance;
QString server_ip = "127.0.0.1";
qint16 server_port = 7890;
bool has_found = false;
void (*_callback) (QString &ip, quint16 port, QByteArray &data)=nullptr;
signals:
void TCPClientConnected();
void TCPClientDisconnected();
signals:
};
#endif // TCPCLIENT_H

121
tcpserver.cpp Normal file
View File

@ -0,0 +1,121 @@
#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();
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)
{
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<tcp_socket_list.length();i++)
{
if (tcp_socket_list[i] == dynamic_cast<QTcpSocket*>(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(ip, tcp_socket_list[i]->peerPort());
tcp_socket_list.removeAt(i);
dynamic_cast<QTcpSocket*>(sender())->deleteLater();
break;
}
}
}
void TCPServer::TCPReadPeer()
{
QTcpSocket* 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(ip, sock->peerPort(),recv);
}
void TCPServer::setCallBack(void (*callback)(QString &ip, quint16 port, QByteArray &data))
{
recvcallback = callback;
}
void TCPServer::setCallBack(void (*callback)(QString &ip, quint16 port))
{
disccallback = callback;
}
void TCPServer::sendToclient(QString ip, quint16 port, QByteArray data)
{
QHostAddress addr(ip);
for (int i=0;i<tcp_socket_list.length();i++)
{
if (addr == tcp_socket_list[i]->peerAddress()&&tcp_socket_list[i]->peerPort()==port)
{
tcp_socket_list[i]->write(data);
break;
}
}
}

36
tcpserver.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
class TCPServer : public QObject
{
Q_OBJECT
public:
static TCPServer* getInstance();
void configAndrun();
void setServer(QString IP, qint16 port);
void setCallBack(void (*callback)(QString &ip, quint16 port, QByteArray &data));//Qt的信号-槽机制实际就是回调函数,
void setCallBack(void (*callback)(QString &ip, quint16 port)); //此处为练手,不使用该机制
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;
QList <QTcpSocket*> tcp_socket_list;
void (*recvcallback) (QString &ip, quint16 port, QByteArray &data)=nullptr;
void (*disccallback) (QString &ip, quint16 port)=nullptr;
static TCPServer tcpserver_instance;
private slots:
void acceptTCPConnection();
void TCPReadPeer();
void discTCPConnection();
signals:
};
#endif // TCPSERVER_H