完成系统管理web端功能,实现系统管理服务端接口,实现登录功能

This commit is contained in:
lixiaoyuan
2025-07-18 09:08:09 +08:00
parent 4a198a7271
commit 7b3f32f334
31 changed files with 1384 additions and 325 deletions

View File

@@ -0,0 +1,28 @@
#include "Communicator.h"
#include "TcpEntity.h"
std::shared_ptr<CommEntity> Communicator::createEntity(DataFields& data)
{
std::string commType = data.getStr("commType");
std::string ip = data.getStr("ip");
int port = data.getInt("port");
int isclient = data.getInt("isclient");
if (commType == "TCP")
{
auto entity = std::make_shared<TcpEntity>();
entity->setHost(ip, port, isclient);
return entity;
}
else if (commType == "MODBUS")
{
}
else if (commType == "ACTIVEX")
{
}
else if (commType == "SDK")
{
}
return nullptr;
}

View File

@@ -0,0 +1,39 @@
#pragma once
#include <memory>
#include <string>
#include "common/DataFields.h"
class CommEntity
{
public:
CommEntity() {}
CommEntity(std::string type) : type(type) {}
void setType(std::string type) { this->type = type; }
// 启动通讯连接
virtual int start() { return 0; };
// 关闭通讯连接
virtual void close() { isCloseRequest_ = true; };
std::string id() { return id_; }
bool isAlive() { return isAlive_; }
bool isConnected() { return isConnected_; }
public:
std::string id_;
bool isAlive_ = false;
bool isConnected_ = false;
bool isCloseRequest_ = false;
std::string type;
};
class Communicator
{
public:
static std::shared_ptr<CommEntity> createEntity(DataFields& data);
};

281
src/protocol/TcpEntity.cpp Normal file
View File

@@ -0,0 +1,281 @@
#include "TcpEntity.h"
#include "common/Utils.h"
#include <sstream>
#include <iomanip>
#include <iostream>
static std::string ToHexText(std::string s)
{
std::stringstream ss;
for (unsigned int i = 0; i < s.size(); ++i)
{
unsigned char ch = s[i];
ss << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << (int)ch << ((i < s.size() - 1) ? " " : "");
}
return ss.str();
}
TcpEntity::TcpEntity(TcpHandler* handler)
: handler_(handler), isClient_(true)
{
}
TcpEntity::~TcpEntity()
{
}
void TcpEntity::setHandler(TcpHandler* handler)
{
handler_ = handler;
}
void TcpEntity::setHost(string host, int port, bool isClient)
{
host_ = host;
port_ = port;
isClient_ = isClient;
}
void TcpEntity::setReconnect(int ms)
{
tReconnect_ = ms;
}
int TcpEntity::start()
{
if (isAlive_)
{
return 1;
}
isAlive_ = true;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
return -1;
}
sockaddr_.sin_family = AF_INET;
sockaddr_.sin_port = htons(port_);
sockaddr_.sin_addr.S_un.S_addr = (isClient_ ? inet_addr(host_.c_str()) : htonl(INADDR_ANY));
std::thread([=]() { this->runThreadTcp(); }).detach();
return 0;
}
void TcpEntity::runThreadTcp()
{
//if (isRequestClose_) { break; }
//std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "TCP thread start ..." << std::endl;
if (isClient_)
{
this->runClientLoop();
}
else
{
this->runServerLoop();
}
isAlive_ = false;
}
void TcpEntity::close()
{
isCloseRequest_ = true;
}
void TcpEntity::runServerLoop()
{
sock_ = ::socket(AF_INET, SOCK_STREAM, 0);
// 绑定套接字 【注意】functional中定义了bind与winsock2的定义发生重载导致异常这里需要使用::bind(加::)
if (::bind(sock_, (SOCKADDR*)&sockaddr_, sizeof(SOCKADDR)) == SOCKET_ERROR)
{
std::cout << "TCP server bind [" << hostport() << "] failed." << std::endl;
return;
}
// 启动监听,准备接收客户请求
if (::listen(sock_, 5) == SOCKET_ERROR)
{
std::cout << "TCP server listen [" << hostport() << "] failed." << std::endl;
return;
}
int addrlen = sizeof(SOCKADDR);
while (1)
{
if (isCloseRequest_) { break; }
Client client;
// 等待客户请求到来
client.sock = ::accept(sock_, (SOCKADDR*)&client.sock_addr, &addrlen);
if (client.sock == INVALID_SOCKET)
{
break;
}
client.host = inet_ntoa(client.sock_addr.sin_addr);
// 存储客户端的连接信息
vecClient_.push_back(client);
// 创建线程处理
std::thread th([=]() { this->runServerRecvLoop(client, client.host); });
th.detach();
}
::closesocket(sock_);
// 连接关闭
for (auto iter = vecClient_.begin(); iter != vecClient_.end(); ++iter)
{
::closesocket(iter->sock);
vecClient_.erase(iter);
}
isCloseRequest_ = false;
}
void TcpEntity::runServerRecvLoop(Client client, std::string client_name)
{
std::vector<char> buf(1024000, 0);
while (1)
{
if (isCloseRequest_ || !isAlive_)
{
break;
}
memset(buf.data(), 0, buf.size());
// 接收数据
int n = ::recv(client.sock, &buf[0], buf.size(), 0);
// 需要判断 errno是否等于 EINTR 。如果errno == EINTR 则说明recv函数是由于程序接收到信号后返回的socket连接还是正常的
if (n <= 0 && GetLastError() != EINTR)
{
// 客户端连接异常(关闭)
break;
}
else
{
}
}
// 连接关闭
for (auto iter = vecClient_.begin(); iter != vecClient_.end(); ++iter)
{
if (iter->sock == client.sock)
{
vecClient_.erase(iter);
break;
}
}
}
void TcpEntity::runClientLoop()
{
// 数据缓存
std::vector<char> buf(1024000, 0);
while (1)
{
if (isCloseRequest_) { break; }
//创建套接字,向服务器发出连接请求
sock_ = ::socket(AF_INET, SOCK_STREAM, 0);
if (::connect(sock_, (SOCKADDR*)&sockaddr_, sizeof(SOCKADDR)) != SOCKET_ERROR)
{
isConnected_ = true;
std::cout << "TCP client connect to [" << hostport() << "] success." << std::endl;
// 连接服务器成功,循环等待接受消息
while (1)
{
if (isCloseRequest_) { break; }
memset(buf.data(), 0, buf.size());
int n = ::recv(sock_, buf.data(), buf.size(), 0);
if (n <= 0 && GetLastError() != EINTR)
{
// TCP通讯异常 关闭连接
::closesocket(sock_);
isConnected_ = false;
break;
}
else
{
// 处理消息
}
}
}
else
{
isConnected_ = false;
std::cout << "TCP client connect to [" << hostport() << "] failed." << std::endl;
}
// 连接异常
if (tReconnect_ > 0)
{
// 重新连接
std::cout << "TCP client [" << hostport() << "] reconnect (" << tReconnect_ << ")." << std::endl;
//std::this_thread::sleep_for(std::chrono::microseconds(tReconnect_));
Sleep(tReconnect_);
}
else
{
// 关闭线程
std::cout << "TCP client [" << hostport() << "] close." << std::endl;
break;
}
}
if (sock_ != INVALID_SOCKET)
{
::closesocket(sock_);
sock_ = INVALID_SOCKET;
isConnected_ = false;
}
if (isCloseRequest_)
{
}
isCloseRequest_ = false;
}
bool TcpEntity::sendData(std::string data, std::string clientId)
{
if (isClient_)
{
// #客户端
if (sock_ == INVALID_SOCKET)
{
//Spdlogger::error("TCP client send data failed, connect error, invalid socket, device: {}:{}.", this->type_, client_code);
return false;
}
int len = ::send(sock_, data.c_str(), data.size(), 0);
//Spdlogger::info("TCP client send data success, data length={}, device: {}:{}.", len, this->type_, client_code);
return (len > 0);
}
else
{
if (vecClient_.size() <= 0)
{
return false;
}
for (auto& client : vecClient_)
{
std::string client_addr = inet_ntoa(client.sock_addr.sin_addr);
::send(client.sock, data.c_str(), data.size(), 0);
}
return true;
}
}
bool TcpEntity::isAlive()
{
return isAlive_;
}
bool TcpEntity::isConnected()
{
return isConnected_;
}

117
src/protocol/TcpEntity.h Normal file
View File

@@ -0,0 +1,117 @@
#ifndef _TcpEntity_H_
#define _TcpEntity_H_
#include <Winsock2.h>
#include <string>
#include <vector>
#include <thread>
#include <functional>
#include "Communicator.h"
using namespace std;
enum class ETcpEvent
{
NUL = 0, //
SRV_SUCCESS, // 服务端启动成功(listen成功)
ACCEPT, // 服务端接收到客户端的连接
CONN_OK, // 作为客户端时,连接成功
CONN_ERR, // 作为客户端时,连接失败
MSG_RECV, // 接收消息
MSG_SEND, // 发送消息
CLOSE, // 断开连接
ERR // 异常错误
};
class TcpHandler;
class TcpParser;
class TcpEntity : public CommEntity, public std::enable_shared_from_this<TcpEntity>
{
public:
struct Client
{
SOCKET sock;
SOCKADDR_IN sock_addr;
std::string host;
std::shared_ptr<TcpParser> parser = nullptr;
};
public:
// 初始化服务端
TcpEntity(TcpHandler* handler = nullptr);
~TcpEntity();
int start() override;
void close() override;
void runThreadTcp();
void setHost(string host, int port, bool is_client);
std::string host() { return host_; }
int port() { return port_; }
std::string hostport() { return host_ + ":" + std::to_string(port_); }
void setReconnect(int ms);
bool isClient() { return isClient_; }
void setHandler(TcpHandler* handler);
bool sendData(std::string data, std::string clientId="");
bool isAlive();
bool isConnected();
std::shared_ptr<TcpParser> parser = nullptr;
private:
void runServerLoop();
void runServerRecvLoop(Client client, std::string client_name);
void runClientLoop();
private:
// 本机的SOCKET对象
SOCKET sock_ = INVALID_SOCKET;
// socket addr信息
SOCKADDR_IN sockaddr_;
// TCP类型是否是客户端 true: 客户端, false: 服务端
bool isClient_ = true;
// 通讯地址,作为客户端时有效
std::string host_;
// 通讯端口
int port_ = 0;
// 重连间隔时间,单位秒
int tReconnect_ = 0;
// 作为服务端时连接的客户端SOCKET
std::vector<Client> vecClient_;
// 回调处理对象
TcpHandler* handler_ = nullptr;
bool isAlive_ = false;
bool isCloseRequest_ = false;
bool isConnected_ = false;
// 状态更新时间戳
int64_t ts_;
int64_t tsHeartbeat_=0;
};
class TcpHandler
{
public:
virtual void onEvent(TcpEntity* entity, TcpEntity::Client* client, ETcpEvent evt, std::string msg) {};
};
#endif // !_TcpEntity_H_