Files
RkApp/ApCreate/NetraLib/src/Netra.cpp

664 lines
20 KiB
C++
Raw Normal View History

2025-09-28 16:03:54 +08:00
#include "Netra.hpp"
namespace QCL
{
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TcpServer::TcpServer(int port)
: port_(port), running_(false), serverSock_(-1) {}
/**
* @brief stop()
*/
TcpServer::~TcpServer()
{
stop();
}
/**
* @brief
* 1. socketTCP
* 2.
* 3.
* 4. 线acceptThread_
*
* @return truefalse
*/
bool TcpServer::start()
{
// 创建socket
serverSock_ = socket(AF_INET, SOCK_STREAM, 0);
if (serverSock_ < 0)
{
std::cerr << "Socket 创建失败\n";
return false;
}
// 设置socket地址结构
sockaddr_in serverAddr;
std::memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port_); // 端口转网络字节序
serverAddr.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡IP
// 允许端口重用,防止服务器异常关闭后端口被占用
int opt = 1;
setsockopt(serverSock_, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
// 绑定端口
if (bind(serverSock_, (sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
{
std::cerr << "绑定失败\n";
return false;
}
// 开始监听最大等待连接数为5
if (listen(serverSock_, 5) < 0)
{
std::cerr << "监听失败\n";
return false;
}
// 设置运行标志为true
running_ = true;
// 启动专门接受客户端连接的线程
acceptThread_ = std::thread(&TcpServer::acceptClients, this);
std::cout << "服务器启动,监听端口:" << port_ << std::endl;
return true;
}
/**
* @brief
* 1. false线退
* 2. socket
* 3. socket
* 4. 线退
*/
void TcpServer::stop()
{
running_ = false;
if (serverSock_ >= 0)
{
close(serverSock_);
serverSock_ = -1;
}
{
// 线程安全关闭所有客户端socket
std::lock_guard<std::mutex> lock(clientsMutex_);
for (int sock : clientSockets_)
{
close(sock);
}
clientSockets_.clear();
}
// 等待监听线程退出
if (acceptThread_.joinable())
acceptThread_.join();
// 等待所有客户端处理线程退出
for (auto &t : clientThreads_)
{
if (t.joinable())
t.join();
}
std::cout << "服务器已停止\n";
}
/**
* @brief acceptClients函数循环监听客户端连接请求
* accept成功
* 1. IP和Socket信息
* 2. 线Socket加入clientSockets_列表
* 3. 线handleClient处理该客户端收发
*/
void TcpServer::acceptClients()
{
while (running_)
{
sockaddr_in clientAddr;
socklen_t clientLen = sizeof(clientAddr);
int clientSock = accept(serverSock_, (sockaddr *)&clientAddr, &clientLen);
if (clientSock < 0)
{
if (running_)
std::cerr << "接受连接失败\n";
continue;
}
// 将客户端IP转换成字符串格式打印
char clientIP[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(clientAddr.sin_addr), clientIP, INET_ADDRSTRLEN);
std::cout << "客户端连接IP: " << clientIP << ", Socket: " << clientSock << std::endl;
{
// 加锁保护共享的clientSockets_容器
std::lock_guard<std::mutex> lock(clientsMutex_);
clientSockets_.push_back(clientSock);
}
}
}
/**
* @brief
* @param clientSock socket
* @param message
*/
void TcpServer::sendToClient(int clientSock, const std::string &message)
{
send(clientSock, message.c_str(), message.size(), 0);
}
/**
* @brief
* @param clientSock socket
*/
std::string TcpServer::receiveFromClient(int clientSock, bool flag)
{
char buffer[1024];
std::memset(buffer, 0, sizeof(buffer));
int flags = flag ? 0 : MSG_DONTWAIT;
ssize_t bytesReceived = recv(clientSock, buffer, sizeof(buffer) - 1, flags);
if (bytesReceived <= 0)
return {};
return std::string(buffer, bytesReceived);
}
/**
* @brief Socket副本线
* @return socket的vector副本
*/
std::vector<int> TcpServer::getClientSockets()
{
std::lock_guard<std::mutex> lock(clientsMutex_);
return clientSockets_;
}
/**
* @brief IP和端口
* @param clientSock Socket描述符
*/
char *TcpServer::getClientIPAndPort(int clientSock)
{
struct sockaddr_in addr;
socklen_t addr_size = sizeof(addr);
// 获取客户端地址信息
if (getpeername(clientSock, (struct sockaddr *)&addr, &addr_size) == -1)
{
perror("getpeername failed");
return NULL;
}
// 分配内存存储结果(格式: "IP:PORT")
char *result = (char *)malloc(INET_ADDRSTRLEN + 10);
if (!result)
return NULL;
// 转换IP和端口
char *ip = inet_ntoa(addr.sin_addr);
unsigned short port = ntohs(addr.sin_port);
snprintf(result, INET_ADDRSTRLEN + 10, "%s:%d", ip, port);
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
WriteFile::WriteFile(const std::string &filePath)
: filePath_(filePath) {}
/**
* @brief 线
*/
bool WriteFile::overwriteText(const std::string &content)
{
std::lock_guard<std::mutex> lock(writeMutex_); // 加锁
return writeToFile(content, std::ios::out | std::ios::trunc);
}
/**
* @brief 线
*/
bool WriteFile::appendText(const std::string &content)
{
std::lock_guard<std::mutex> lock(writeMutex_);
return writeToFile(content, std::ios::out | std::ios::app);
}
/**
* @brief 线
*/
bool WriteFile::overwriteBinary(const std::vector<char> &data)
{
std::lock_guard<std::mutex> lock(writeMutex_);
return writeBinary(data, std::ios::out | std::ios::trunc | std::ios::binary);
}
/**
* @brief 线
*/
bool WriteFile::appendBinary(const std::vector<char> &data)
{
std::lock_guard<std::mutex> lock(writeMutex_);
return writeBinary(data, std::ios::out | std::ios::app | std::ios::binary);
}
/**
* @brief
*/
bool WriteFile::writeToFile(const std::string &content, std::ios::openmode mode)
{
std::ofstream file(filePath_, mode);
if (!file.is_open())
return false;
file << content;
file.close();
return true;
}
/**
* @brief
*/
bool WriteFile::writeBinary(const std::vector<char> &data, std::ios::openmode mode)
{
std::ofstream file(filePath_, mode);
if (!file.is_open())
return false;
file.write(data.data(), data.size());
file.close();
return true;
}
size_t WriteFile::countBytesPattern(const std::string &pattern, bool includePattern)
{
std::lock_guard<std::mutex> lock(writeMutex_);
if (pattern.empty())
return 0;
std::ifstream file(filePath_, std::ios::binary);
if (!file.is_open())
return 0;
const size_t chunkSize = 4096;
std::string buffer;
buffer.reserve(chunkSize * 2);
size_t totalRead = 0;
char chunk[chunkSize];
while (file.read(chunk, chunkSize) || file.gcount() > 0)
{
size_t bytesRead = file.gcount();
buffer.append(chunk, bytesRead);
size_t pos = buffer.find(pattern);
if (pos != std::string::npos)
{
size_t absolutePos = totalRead + pos; // 关键:加上 totalRead
return includePattern ? (absolutePos + pattern.size()) : absolutePos;
}
if (buffer.size() > pattern.size())
buffer.erase(0, buffer.size() - pattern.size());
totalRead += bytesRead; // 读完后再累计
}
return 0;
}
bool WriteFile::writeAfterPatternOrAppend(const std::string &pattern, const std::string &content)
{
std::lock_guard<std::mutex> lock(writeMutex_);
// 读取整个文件
std::ifstream in(filePath_, std::ios::binary);
if (!in.is_open())
return false;
std::string fileData((std::istreambuf_iterator<char>(in)), {});
in.close();
size_t pos = fileData.find(pattern);
if (pos != std::string::npos)
{
// 模式存在,插入位置在模式结尾
pos += pattern.size();
// 删除模式后所有内容
if (pos < fileData.size())
fileData.erase(pos);
// 插入新内容
fileData.insert(pos, content);
}
else
{
// 模式不存在,直接追加到文件末尾
if (!fileData.empty() && fileData.back() != '\n')
fileData += '\n'; // 保证换行
fileData += content;
}
// 写回文件
std::ofstream out(filePath_, std::ios::binary | std::ios::trunc);
if (!out.is_open())
return false;
out.write(fileData.data(), fileData.size());
return true;
}
bool WriteFile::overwriteAtPos(const std::string &content, size_t pos, size_t length)
{
std::lock_guard<std::mutex> lock(writeMutex_);
// 打开文件读取
std::ifstream in(filePath_, std::ios::binary);
if (!in.is_open())
return false;
std::string fileData((std::istreambuf_iterator<char>(in)), {});
in.close();
// 边界检查
if (pos >= fileData.size())
return false; // pos 超过文件范围,无法覆盖
// 生成要覆盖的实际数据块
std::string overwriteBlock;
if (content.size() >= length)
{
overwriteBlock = content.substr(0, length);
}
else
{
overwriteBlock = content;
overwriteBlock.append(length - content.size(), '\0'); // 补齐
}
// 计算实际可写范围
size_t maxWritable = std::min(length, fileData.size() - pos);
// 覆盖
fileData.replace(pos, maxWritable, overwriteBlock.substr(0, maxWritable));
// 写回文件
std::ofstream out(filePath_, std::ios::binary | std::ios::trunc);
if (!out.is_open())
return false;
out.write(fileData.data(), fileData.size());
return true;
}
bool WriteFile::insertAfterPos(const std::string &content, size_t pos, size_t length)
{
std::lock_guard<std::mutex> lock(writeMutex_);
// 打开文件读取
std::ifstream in(filePath_, std::ios::binary);
if (!in.is_open())
return false;
std::string fileData((std::istreambuf_iterator<char>(in)), {});
in.close();
// 边界检查
if (pos > fileData.size())
pos = fileData.size(); // 如果 pos 超出范围,就视为文件末尾
// 生成要插入的实际数据块
std::string insertBlock;
if (content.size() >= length)
{
insertBlock = content.substr(0, length); // 只取前 length 个字节
}
else
{
insertBlock = content; // 全部内容
insertBlock.append(length - content.size(), '\0'); // 补足空字节
}
// 插入到 pos 后面
fileData.insert(pos + 1, insertBlock);
// 写回文件
std::ofstream out(filePath_, std::ios::binary | std::ios::trunc);
if (!out.is_open())
return false;
out.write(fileData.data(), fileData.size());
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ReadFile::ReadFile(const std::string &filename) : filename_(filename) {}
ReadFile::~ReadFile()
{
std::lock_guard<std::mutex> lock(mtx_);
Close();
}
bool ReadFile::Open()
{
std::lock_guard<std::mutex> lock(mtx_);
if (file_.is_open())
file_.close();
file_.open(filename_, std::ios::in | std::ios::binary);
return file_.is_open();
}
void ReadFile::Close()
{
if (file_.is_open())
{
std::lock_guard<std::mutex> lock(mtx_);
file_.close();
}
}
bool ReadFile::IsOpen() const
{
std::lock_guard<std::mutex> lock(mtx_);
return file_.is_open();
}
std::string ReadFile::ReadAllText()
{
std::lock_guard<std::mutex> lock(mtx_);
if (!file_.is_open() && !Open())
return "";
std::ostringstream ss;
ss << file_.rdbuf();
return ss.str();
}
std::vector<char> ReadFile::ReadAllBinary()
{
std::lock_guard<std::mutex> lock(mtx_);
if (!file_.is_open() && !Open())
return {};
return ReadBytes(GetFileSize());
}
std::vector<std::string> ReadFile::ReadLines()
{
// std::lock_guard<std::mutex> lock(mtx_);
// if (!file_.is_open() && !Open())
// return {};
// std::vector<std::string> lines;
// std::string line;
// while (std::getline(file_, line))
// {
// lines.push_back(line);
// }
// return lines;
std::lock_guard<std::mutex> lock(mtx_);
if (!file_.is_open()) {
file_.open(filename_, std::ios::in | std::ios::binary);
if (!file_.is_open()) return {};
}
file_.clear();
file_.seekg(0, std::ios::beg);
std::vector<std::string> lines;
std::string line;
while (std::getline(file_, line)) lines.push_back(line);
return lines;
}
std::vector<char> ReadFile::ReadBytes(size_t count)
{
std::lock_guard<std::mutex> lock(mtx_);
if (!file_.is_open() && !Open())
return {};
std::vector<char> buffer(count);
file_.read(buffer.data(), count);
buffer.resize(file_.gcount());
return buffer;
}
size_t ReadFile::GetBytesBefore(const std::string &marker, bool includeMarker)
{
std::lock_guard<std::mutex> lock(mtx_);
if (!file_.is_open() && !Open())
return 0;
file_.clear(); // 清除EOF和错误状态
file_.seekg(0, std::ios::beg); // 回到文件开头
const size_t chunkSize = 4096;
std::string buffer;
buffer.reserve(chunkSize * 2);
size_t totalRead = 0;
char chunk[chunkSize];
while (file_.read(chunk, chunkSize) || file_.gcount() > 0)
{
buffer.append(chunk, file_.gcount());
size_t pos = buffer.find(marker);
if (pos != std::string::npos)
{
// 如果 includeMarker 为 true返回包含 marker 的长度
if (includeMarker)
return pos + marker.size();
else
return pos;
}
// 保留末尾部分,避免 buffer 无限增长
if (buffer.size() > marker.size())
buffer.erase(0, buffer.size() - marker.size());
totalRead += file_.gcount();
}
return 0;
}
std::vector<char> ReadFile::ReadBytesFrom(size_t pos, size_t count)
{
std::lock_guard<std::mutex> lock(mtx_);
if (!file_.is_open() && !Open())
return {};
size_t filesize = GetFileSize();
if (pos >= filesize)
return {}; // 起始位置超出文件大小
file_.clear(); // 清除 EOF 和错误状态
file_.seekg(pos, std::ios::beg);
if (!file_)
return {};
size_t bytes_to_read = count;
if (count == 0 || pos + count > filesize)
bytes_to_read = filesize - pos; // 读取到文件末尾
std::vector<char> buffer(bytes_to_read);
file_.read(buffer.data(), bytes_to_read);
// 实际读取的字节数可能少于请求的数量
buffer.resize(file_.gcount());
return buffer;
}
bool ReadFile::FileExists() const
{
return std::filesystem::exists(filename_);
}
size_t ReadFile::GetFileSize() const
{
if (!FileExists())
return 0;
return std::filesystem::file_size(filename_);
}
void ReadFile::Reset()
{
std::lock_guard<std::mutex> lock(mtx_);
if (file_.is_open())
{
file_.clear();
file_.seekg(0, std::ios::beg);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 屏蔽所有信号
void blockAllSignals()
{
// 忽略全部的信号
for (int ii = 1; ii <= 64; ii++)
signal(ii, SIG_IGN);
}
std::string Ltrim(const std::string &s)
{
size_t start = 0;
while (start < s.size() && std::isspace(static_cast<unsigned char>(s[start])))
{
++start;
}
return s.substr(start);
}
std::string Rtrim(const std::string &s)
{
if (s.empty())
return s;
size_t end = s.size();
while (end > 0 && std::isspace(static_cast<unsigned char>(s[end - 1])))
{
--end;
}
return s.substr(0, end);
}
std::string LRtrim(const std::string &s)
{
return Ltrim(Rtrim(s));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}