2024-04-24 10:25:44 +08:00
|
|
|
#pragma once
|
|
|
|
|
#include "Singleton.h"
|
|
|
|
|
#include "l_squirrel.h"
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <asio.hpp>
|
2024-08-17 13:39:51 +08:00
|
|
|
#include <spdlog/spdlog.h>
|
|
|
|
|
#include <spdlog/sinks/stdout_color_sinks.h>
|
|
|
|
|
#include <spdlog/sinks/basic_file_sink.h>
|
2024-04-24 10:25:44 +08:00
|
|
|
|
|
|
|
|
extern HSQUIRRELVM v;
|
|
|
|
|
extern std::recursive_mutex SqMtx;
|
|
|
|
|
|
|
|
|
|
using namespace asio;
|
|
|
|
|
using asio::ip::tcp;
|
|
|
|
|
|
|
|
|
|
class Client
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
asio::io_context io_context;
|
|
|
|
|
tcp::resolver resolver;
|
|
|
|
|
tcp::socket socket;
|
|
|
|
|
tcp::resolver::results_type endpoint;
|
|
|
|
|
std::array<char, 8192> buffer;
|
|
|
|
|
std::array<char, 8192000> PackData;
|
|
|
|
|
std::size_t writeDataSize = 0;
|
|
|
|
|
std::size_t receivedDataSize = 0;
|
|
|
|
|
std::string Ip = "192.168.200.27";
|
|
|
|
|
// std::string Ip = "127.0.0.1";
|
|
|
|
|
std::string Port = "65109";
|
2024-09-07 15:18:28 +08:00
|
|
|
std::mutex SizeMtx;
|
|
|
|
|
std::mutex ClearFlagMtx;
|
2024-04-24 10:25:44 +08:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
bool ConnectState = false;
|
2024-09-07 15:18:28 +08:00
|
|
|
bool ClearFlag = false;
|
|
|
|
|
int LogiThreadSize = 0;
|
2024-04-24 10:25:44 +08:00
|
|
|
|
2024-08-17 13:39:51 +08:00
|
|
|
std::fstream file;
|
|
|
|
|
|
2024-04-24 10:25:44 +08:00
|
|
|
public:
|
2024-04-30 03:01:48 +08:00
|
|
|
Client(asio::io_context &io_context, std::string Ip, std::string Port)
|
2024-04-24 10:25:44 +08:00
|
|
|
: resolver(io_context),
|
|
|
|
|
socket(io_context)
|
|
|
|
|
{
|
|
|
|
|
endpoint = resolver.resolve(Ip, Port);
|
2024-05-12 09:07:41 +08:00
|
|
|
this->Ip = Ip;
|
|
|
|
|
this->Port = Port;
|
2024-04-24 10:25:44 +08:00
|
|
|
PackData.fill(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void start()
|
|
|
|
|
{
|
|
|
|
|
async_connect(socket, endpoint, [this](const asio::error_code &error, const tcp::endpoint &endpoint)
|
|
|
|
|
{
|
|
|
|
|
if (!error) {
|
|
|
|
|
ConnectState = true;
|
|
|
|
|
read();
|
|
|
|
|
std::lock_guard<std::recursive_mutex> lock(SqMtx);
|
|
|
|
|
SQInteger top = sq_gettop(v); // saves the stack size before the call
|
|
|
|
|
sq_pushroottable(v); // pushes the global table
|
|
|
|
|
sq_pushstring(v, _SC("OnGatewaySocketConnect"), -1);
|
|
|
|
|
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
|
|
|
|
{ // gets the field 'foo' from the global table
|
|
|
|
|
sq_pushroottable(v); // push the 'this' (in this case is the global table)
|
|
|
|
|
sq_call(v, 1, SQFalse, SQTrue); // calls the function
|
|
|
|
|
}
|
|
|
|
|
sq_settop(v, top); // restores the original stack size
|
|
|
|
|
io_context.poll(); // 处理一次事件循环,避免主线程阻塞
|
|
|
|
|
} else {
|
2025-03-27 20:24:19 +08:00
|
|
|
// std::cerr << "Error connecting to server: " << error.message() << std::endl;
|
2024-08-17 13:39:51 +08:00
|
|
|
start();
|
2024-04-24 10:25:44 +08:00
|
|
|
} });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void read()
|
|
|
|
|
{
|
|
|
|
|
socket.async_read_some(asio::buffer(buffer), [this](const asio::error_code &error, std::size_t bytes_transferred)
|
|
|
|
|
{
|
|
|
|
|
if (!error) {
|
2024-09-07 15:18:28 +08:00
|
|
|
if (ClearFlag)
|
|
|
|
|
ClearPack();
|
2024-08-17 13:39:51 +08:00
|
|
|
for (std::size_t i = 0; i < bytes_transferred; ++i)
|
|
|
|
|
{
|
|
|
|
|
PackData[writeDataSize + i] = buffer[i];
|
|
|
|
|
}
|
2024-09-07 15:18:28 +08:00
|
|
|
SizeMtx.lock();
|
|
|
|
|
writeDataSize += bytes_transferred;
|
|
|
|
|
SizeMtx.unlock();
|
|
|
|
|
read();
|
2024-04-24 10:25:44 +08:00
|
|
|
} else {
|
|
|
|
|
std::cerr << "Error reading data: " << error.message() << std::endl;
|
|
|
|
|
reconnect();
|
|
|
|
|
} });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void reconnect()
|
|
|
|
|
{
|
|
|
|
|
ConnectState = false;
|
|
|
|
|
std::cout << "服务器断开连接,尝试重连." << std::endl;
|
|
|
|
|
// 执行重连操作
|
|
|
|
|
// 关闭当前连接
|
|
|
|
|
socket.close();
|
|
|
|
|
// 重新解析端点
|
|
|
|
|
endpoint = resolver.resolve(Ip, Port);
|
|
|
|
|
// 重新连接
|
|
|
|
|
async_connect(socket, endpoint, [this](const asio::error_code &error, const tcp::endpoint &endpoint)
|
|
|
|
|
{
|
|
|
|
|
if (!error) {
|
|
|
|
|
ConnectState = true;
|
|
|
|
|
std::lock_guard<std::recursive_mutex> lock(SqMtx);
|
|
|
|
|
SQInteger top = sq_gettop(v); // saves the stack size before the call
|
|
|
|
|
sq_pushroottable(v); // pushes the global table
|
|
|
|
|
sq_pushstring(v, _SC("OnGatewaySocketConnect"), -1);
|
|
|
|
|
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
|
|
|
|
{ // gets the field 'foo' from the global table
|
|
|
|
|
sq_pushroottable(v); // push the 'this' (in this case is the global table)
|
|
|
|
|
sq_call(v, 1, SQFalse, SQTrue); // calls the function
|
|
|
|
|
}
|
|
|
|
|
sq_settop(v, top); // restores the original stack size
|
|
|
|
|
|
|
|
|
|
read();
|
|
|
|
|
} else {
|
|
|
|
|
std::cerr << "Error reconnecting to server: " << error.message() << std::endl;
|
|
|
|
|
// 可以在此处添加重连失败的处理逻辑
|
|
|
|
|
reconnect();
|
|
|
|
|
} });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void send(unsigned char *message, int Length)
|
|
|
|
|
{
|
|
|
|
|
async_write(socket, asio::buffer(message, Length), [this](const asio::error_code &error, std::size_t bytes_transferred)
|
|
|
|
|
{
|
|
|
|
|
if (!error) {
|
|
|
|
|
// std::cout << "Message sent" << std::endl;
|
|
|
|
|
} else {
|
|
|
|
|
std::cerr << "Error sending message: " << error.message() << std::endl;
|
|
|
|
|
} });
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-07 15:18:28 +08:00
|
|
|
void ClearPack()
|
|
|
|
|
{
|
|
|
|
|
SizeMtx.lock();
|
|
|
|
|
// 复制已读大小开始到结束到 开始 作用删除前已读大小的数据
|
|
|
|
|
std::copy(PackData.begin() + receivedDataSize, PackData.end(), PackData.begin());
|
|
|
|
|
// 将最后元素设置为0
|
|
|
|
|
std::fill(PackData.end() - receivedDataSize, PackData.end(), 0);
|
|
|
|
|
// 写的大小重置
|
|
|
|
|
writeDataSize -= receivedDataSize;
|
|
|
|
|
// 读的大小重置
|
|
|
|
|
receivedDataSize = 0;
|
|
|
|
|
SizeMtx.unlock();
|
|
|
|
|
ClearFlagMtx.lock();
|
|
|
|
|
ClearFlag = false;
|
|
|
|
|
ClearFlagMtx.unlock();
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-24 10:25:44 +08:00
|
|
|
void PackLogic()
|
|
|
|
|
{
|
2024-09-07 15:18:28 +08:00
|
|
|
int RealSize = 0;
|
|
|
|
|
int RealReadSize = -1;
|
|
|
|
|
|
|
|
|
|
if (SizeMtx.try_lock())
|
|
|
|
|
{
|
|
|
|
|
receivedDataSize += LogiThreadSize;
|
|
|
|
|
LogiThreadSize = 0;
|
|
|
|
|
RealSize = writeDataSize;
|
|
|
|
|
RealReadSize = receivedDataSize;
|
|
|
|
|
SizeMtx.unlock();
|
|
|
|
|
}
|
2024-04-24 10:25:44 +08:00
|
|
|
// 如果包长度不够直接返回
|
2024-09-07 15:18:28 +08:00
|
|
|
if (RealSize < 4 || RealReadSize == -1)
|
2024-04-24 10:25:44 +08:00
|
|
|
return;
|
|
|
|
|
// 如果里面已经读了超过一半的大小了
|
2024-09-07 15:18:28 +08:00
|
|
|
if (RealSize >= 40960)
|
2024-04-24 10:25:44 +08:00
|
|
|
{
|
2024-09-07 15:18:28 +08:00
|
|
|
if (!ClearFlag)
|
|
|
|
|
{
|
|
|
|
|
ClearFlagMtx.lock();
|
|
|
|
|
ClearFlag = true;
|
|
|
|
|
ClearFlagMtx.unlock();
|
|
|
|
|
}
|
2024-04-24 10:25:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned char *Count = new unsigned char[4];
|
2024-08-17 13:39:51 +08:00
|
|
|
|
2024-09-07 15:18:28 +08:00
|
|
|
std::copy(PackData.begin() + RealReadSize, PackData.begin() + 4 + RealReadSize, Count);
|
2024-08-17 13:39:51 +08:00
|
|
|
|
2024-04-24 10:25:44 +08:00
|
|
|
int PackSize = ByteLittleToInt(Count);
|
|
|
|
|
delete[] Count;
|
2024-09-07 15:18:28 +08:00
|
|
|
|
2024-08-17 13:39:51 +08:00
|
|
|
// 如果包长度不够或者缓冲区长度直接返回
|
2024-09-07 15:18:28 +08:00
|
|
|
if (PackSize <= 0 || ((RealSize - RealReadSize - 4) < PackSize))
|
2024-04-24 10:25:44 +08:00
|
|
|
return;
|
2024-09-07 15:18:28 +08:00
|
|
|
|
2024-08-17 13:39:51 +08:00
|
|
|
char *StrBuffer = new char[PackSize];
|
|
|
|
|
|
2024-09-07 15:18:28 +08:00
|
|
|
std::copy(PackData.begin() + 4 + RealReadSize, PackData.begin() + 4 + PackSize + RealReadSize, StrBuffer);
|
2024-08-17 13:39:51 +08:00
|
|
|
std::string Str(StrBuffer, PackSize);
|
|
|
|
|
delete[] StrBuffer;
|
|
|
|
|
|
|
|
|
|
// 包数据大小读取的偏移 这次读了多少
|
2024-09-07 15:18:28 +08:00
|
|
|
LogiThreadSize += (4 + PackSize);
|
2024-04-24 10:25:44 +08:00
|
|
|
|
2024-07-19 13:36:35 +08:00
|
|
|
// std::cout << "包大小: " << PackSize << std::endl;
|
|
|
|
|
// std::cout << "包内容: " << Str << std::endl;
|
|
|
|
|
// std::cout << "收到了第: " << TestCode << "个包" << std::endl;
|
2024-08-17 13:39:51 +08:00
|
|
|
// spdlog::info(Str);
|
2024-04-24 10:25:44 +08:00
|
|
|
|
|
|
|
|
std::lock_guard<std::recursive_mutex> lock(SqMtx);
|
|
|
|
|
SQInteger top = sq_gettop(v); // saves the stack size before the call
|
|
|
|
|
sq_pushroottable(v); // pushes the global table
|
|
|
|
|
sq_pushstring(v, _SC("OnGatewaySocketMsg"), -1);
|
|
|
|
|
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
|
|
|
|
{ // gets the field 'foo' from the global table
|
|
|
|
|
sq_pushroottable(v); // push the 'this' (in this case is the global table)
|
2024-08-17 13:39:51 +08:00
|
|
|
sq_pushstring(v, Str.c_str(), PackSize);
|
2024-04-24 10:25:44 +08:00
|
|
|
sq_call(v, 2, SQFalse, SQTrue); // calls the function
|
|
|
|
|
}
|
|
|
|
|
sq_settop(v, top); // restores the original stack size
|
2024-08-17 13:39:51 +08:00
|
|
|
// TestCode++;
|
2024-04-24 10:25:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ByteLittleToInt(unsigned char *Count)
|
|
|
|
|
{
|
|
|
|
|
int int1 = Count[0] & 0xff;
|
|
|
|
|
int int2 = (Count[1] & 0xff) << 8;
|
|
|
|
|
int int3 = (Count[2] & 0xff) << 16;
|
|
|
|
|
int int4 = (Count[3] & 0xff) << 24;
|
|
|
|
|
|
|
|
|
|
return int1 | int2 | int3 | int4;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class l_socket
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
private:
|
|
|
|
|
l_socket() {} // private constructor to prevent instantiation
|
|
|
|
|
l_socket(const l_socket &) = delete; // disable copy constructor
|
|
|
|
|
l_socket &operator=(const l_socket &) = delete; // disable assignment operator
|
|
|
|
|
Client *ClientObj;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
bool InitState = false;
|
|
|
|
|
static l_socket &getInstance()
|
|
|
|
|
{
|
|
|
|
|
static l_socket instance;
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InitSqr();
|
|
|
|
|
void InitPackLogic();
|
2024-04-30 03:01:48 +08:00
|
|
|
void Init(std::string Ip, std::string Port);
|
2024-04-24 10:25:44 +08:00
|
|
|
void Send(const SQChar *Pck);
|
|
|
|
|
void Logic();
|
|
|
|
|
void IntToByteLittle(unsigned char *b, int Count);
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
};
|