From 597c394120638e0c580aad60c8e4ac34a2c2189d Mon Sep 17 00:00:00 2001 From: qingjiao Date: Mon, 29 Dec 2025 09:55:17 +0800 Subject: [PATCH] V0.1 --- CC_SDK_VS/CCMutex.cpp | 66 + CC_SDK_VS/CCMutex.h | 26 + CC_SDK_VS/CCThread.cpp | 89 ++ CC_SDK_VS/CCThread.h | 41 + CC_SDK_VS/CCThreadPool.cpp | 78 ++ CC_SDK_VS/CCThreadPool.h | 42 + CC_SDK_VS/Socket/CCClientSocket.cpp | 164 +++ CC_SDK_VS/Socket/CCClientSocket.h | 52 + CC_SDK_VS/Socket/CCDatagramSocket.cpp | 195 +++ CC_SDK_VS/Socket/CCDatagramSocket.h | 92 ++ CC_SDK_VS/Socket/CCServerSocket.cpp | 78 ++ CC_SDK_VS/Socket/CCServerSocket.h | 32 + CC_SDK_VS/Socket/CCSocket.cpp | 1183 +++++++++++++++++ CC_SDK_VS/Socket/CCSocket.h | 208 +++ CC_SDK_VS/TL/Array_CTL.h | 118 ++ CC_SDK_VS/TL/AutoDestruct.h | 65 + CC_SDK_VS/TL/List.h | 202 +++ CC_SDK_VS/TL/Map.h | 209 +++ CC_SDK_VS/TL/Map_CTL.h | 409 ++++++ CC_SDK_VS/TL/Queue.h | 69 + .../WebSocket}/CCWebSocket.cpp | 0 .../WebSocket}/CCWebSocket.h | 2 + {WebSocket => CC_SDK_VS/WebSocket}/base64.cpp | 0 {WebSocket => CC_SDK_VS/WebSocket}/base64.h | 0 {WebSocket => CC_SDK_VS/WebSocket}/sha1.h | 0 .../WebSocket}/sha1_portable.cpp | 0 .../WebSocket}/string_helper.cpp | 0 .../WebSocket}/string_helper.h | 0 .../WebSocket}/string_helper.inl | 0 .../WebSocket}/ws_endpoint.cpp | 0 .../WebSocket}/ws_endpoint.h | 0 .../WebSocket}/ws_packet.cpp | 0 .../WebSocket}/ws_packet.h | 0 CC_SDK_VS/base/CCByte.h | 188 +++ CC_SDK_VS/base/CCByteArray.cpp | 454 +++++++ CC_SDK_VS/base/CCByteArray.h | 331 +++++ CMakeLists.txt | 15 +- 37 files changed, 4405 insertions(+), 3 deletions(-) create mode 100755 CC_SDK_VS/CCMutex.cpp create mode 100755 CC_SDK_VS/CCMutex.h create mode 100755 CC_SDK_VS/CCThread.cpp create mode 100755 CC_SDK_VS/CCThread.h create mode 100755 CC_SDK_VS/CCThreadPool.cpp create mode 100755 CC_SDK_VS/CCThreadPool.h create mode 100644 CC_SDK_VS/Socket/CCClientSocket.cpp create mode 100644 CC_SDK_VS/Socket/CCClientSocket.h create mode 100644 CC_SDK_VS/Socket/CCDatagramSocket.cpp create mode 100644 CC_SDK_VS/Socket/CCDatagramSocket.h create mode 100644 CC_SDK_VS/Socket/CCServerSocket.cpp create mode 100644 CC_SDK_VS/Socket/CCServerSocket.h create mode 100644 CC_SDK_VS/Socket/CCSocket.cpp create mode 100644 CC_SDK_VS/Socket/CCSocket.h create mode 100644 CC_SDK_VS/TL/Array_CTL.h create mode 100644 CC_SDK_VS/TL/AutoDestruct.h create mode 100644 CC_SDK_VS/TL/List.h create mode 100644 CC_SDK_VS/TL/Map.h create mode 100644 CC_SDK_VS/TL/Map_CTL.h create mode 100644 CC_SDK_VS/TL/Queue.h rename {WebSocket => CC_SDK_VS/WebSocket}/CCWebSocket.cpp (100%) rename {WebSocket => CC_SDK_VS/WebSocket}/CCWebSocket.h (74%) rename {WebSocket => CC_SDK_VS/WebSocket}/base64.cpp (100%) rename {WebSocket => CC_SDK_VS/WebSocket}/base64.h (100%) rename {WebSocket => CC_SDK_VS/WebSocket}/sha1.h (100%) rename {WebSocket => CC_SDK_VS/WebSocket}/sha1_portable.cpp (100%) rename {WebSocket => CC_SDK_VS/WebSocket}/string_helper.cpp (100%) rename {WebSocket => CC_SDK_VS/WebSocket}/string_helper.h (100%) rename {WebSocket => CC_SDK_VS/WebSocket}/string_helper.inl (100%) rename {WebSocket => CC_SDK_VS/WebSocket}/ws_endpoint.cpp (100%) rename {WebSocket => CC_SDK_VS/WebSocket}/ws_endpoint.h (100%) rename {WebSocket => CC_SDK_VS/WebSocket}/ws_packet.cpp (100%) rename {WebSocket => CC_SDK_VS/WebSocket}/ws_packet.h (100%) create mode 100644 CC_SDK_VS/base/CCByte.h create mode 100644 CC_SDK_VS/base/CCByteArray.cpp create mode 100644 CC_SDK_VS/base/CCByteArray.h diff --git a/CC_SDK_VS/CCMutex.cpp b/CC_SDK_VS/CCMutex.cpp new file mode 100755 index 0000000..f2af7a2 --- /dev/null +++ b/CC_SDK_VS/CCMutex.cpp @@ -0,0 +1,66 @@ +#include "CCMutex.h" + +CTL::AutoLock::AutoLock(Mutex& mutex_t) +{ + this->Mutex_M = &mutex_t; + if (this->Mutex_M) + { + this->Mutex_M->lock(); + } +} + +CTL::AutoLock::~AutoLock() +{ + if (this->Mutex_M) + { + this->Mutex_M->unlock(); + } +} + +CTL::AutoLock& CTL::AutoLock::operator=(AutoLock&) +{ + return *this; +} + +CTL::Mutex::Mutex() +{ + g_Mutex = ::CreateMutex(NULL, FALSE, NULL); +} + +CTL::Mutex::~Mutex() +{ + if (g_Mutex) + { + CloseHandle(g_Mutex); + } + g_Mutex = nullptr; +} + +bool CTL::Mutex::lock() +{ + TryLock_M = true; + if (g_Mutex) + { + return WaitForSingleObject(g_Mutex, INFINITE) == WAIT_OBJECT_0; + } + return false; +} + +void CTL::Mutex::unlock() +{ + TryLock_M = false; + if (g_Mutex) + { + ReleaseMutex(g_Mutex); + } +} + +bool CTL::Mutex::try_lock() +{ + if (g_Mutex) + { + return WaitForSingleObject(g_Mutex, 0) == WAIT_OBJECT_0; + } + + return false; +} diff --git a/CC_SDK_VS/CCMutex.h b/CC_SDK_VS/CCMutex.h new file mode 100755 index 0000000..cd5b6c4 --- /dev/null +++ b/CC_SDK_VS/CCMutex.h @@ -0,0 +1,26 @@ +#pragma once +#include "Windows.h" + +namespace CTL { + class Mutex + { + public: + Mutex(); + ~Mutex(); + bool lock(); + void unlock(); + bool try_lock(); + private: + HANDLE g_Mutex; + bool TryLock_M = false; + }; + class AutoLock + { + public: + AutoLock(Mutex& mutex_t); + ~AutoLock(); + private: + Mutex* Mutex_M; + AutoLock& operator = (AutoLock&); + }; +} \ No newline at end of file diff --git a/CC_SDK_VS/CCThread.cpp b/CC_SDK_VS/CCThread.cpp new file mode 100755 index 0000000..c466315 --- /dev/null +++ b/CC_SDK_VS/CCThread.cpp @@ -0,0 +1,89 @@ +#include "CCThread.h" + +CTL::Thread::Thread() +{ +} + +// ÒÆ³ýÁËÒÆ¶¯¹¹Ô캯Êý +// CTL::Thread::Thread(Thread&& other) +// { +// ... +// } + +CTL::Thread::~Thread() +{ +} + +DWORD CTL::Thread::GetThreadId() const +{ + return this->dwThreadId; +} + +void CTL::Thread::Wait() +{ + Mode = 0; + hThread = CreateThread( + NULL, + 0, + MyThreadFunction, + this, + 0, + &dwThreadId + ); + if (hThread) + { + ::WaitForSingleObject(hThread, INFINITE); + } + while (!this->IsStop) + { + Thread::SleepMS(50); + } +} + +void CTL::Thread::Start() +{ + Mode = 1; + hThread = CreateThread( + NULL, + 0, + MyThreadFunction, + this, + 0, + &dwThreadId + ); +} + +void CTL::Thread::StartDetch() +{ + Start(); + Mode = 2; + CloseHandle(hThread); + hThread = nullptr; +} + +void CTL::Thread::SleepMS(int ms) +{ + ::Sleep(ms); +} + +DWORD __stdcall CTL::Thread::MyThreadFunction(LPVOID lpParam) +{ + Thread* pThread = (Thread*)lpParam; + if (pThread && pThread->task_Fun) + { + pThread->IsStop = false; + try + { + pThread->task_Fun(); + } + catch (const std::exception&) + { + } + if (pThread->hThread && (pThread->Mode == 0 || pThread->Mode == 1)) + { + CloseHandle(pThread->hThread); + } + pThread->IsStop = true; + } + return 0; +} \ No newline at end of file diff --git a/CC_SDK_VS/CCThread.h b/CC_SDK_VS/CCThread.h new file mode 100755 index 0000000..af13ba0 --- /dev/null +++ b/CC_SDK_VS/CCThread.h @@ -0,0 +1,41 @@ +#pragma once +#include "Windows.h" +#include + +namespace CTL { + class Thread + { + public: + Thread(); + template + Thread(FUN&& fun, ARGS&& ...Args); + ~Thread(); + DWORD GetThreadId() const; + template + bool SetThread(FUN&& fun, ARGS&& ...Args); + void Wait(); + void Start(); + void StartDetch(); + static void SleepMS(int ms); + private: + static DWORD WINAPI MyThreadFunction(LPVOID lpParam); + int Mode = 0; + bool IsStop = false; + public: + private: + HANDLE hThread; + DWORD dwThreadId; + std::function task_Fun; + }; + template + inline Thread::Thread(FUN&& fun, ARGS && ...Args) + { + SetThread(fun, Args...); + } + template + inline bool Thread::SetThread(FUN&& fun, ARGS && ...Args) + { + task_Fun = std::bind(std::forward(fun), std::forward(Args)...); + return task_Fun ? true : false; + } +} \ No newline at end of file diff --git a/CC_SDK_VS/CCThreadPool.cpp b/CC_SDK_VS/CCThreadPool.cpp new file mode 100755 index 0000000..2b88517 --- /dev/null +++ b/CC_SDK_VS/CCThreadPool.cpp @@ -0,0 +1,78 @@ +#include "CCThreadPool.h" + +CTL::ThreadPool::ThreadPool() +{ +} + +CTL::ThreadPool::~ThreadPool() +{ + Stop(); +} + +bool CTL::ThreadPool::InitStart(int Core) +{ + this->M_Core = Core; + isRunning = true; + for (size_t i = 0; i < M_Core; i++) + { + auto TB = new TaskBase(); + TB->ID = i; + TB->IsRunning = true; + TB->thread_t = new Thread(&ThreadPool::Worker, this, i); + m_Threads.push_back(TB); + TB->thread_t->Start(); + } + return true; // ÒÆ³öÑ­»· +} + +void CTL::ThreadPool::Stop() +{ + if (!isRunning) + { + return; + } + isRunning = false; + for (size_t i = 0; i < this->M_Core; i++) + { + auto thread_ = m_Threads[i]; + if (thread_ && thread_->thread_t) + { + thread_->thread_t->Wait(); + delete thread_->thread_t; + thread_->thread_t = nullptr; + delete thread_; + thread_ = nullptr; + } + } +} + +void CTL::ThreadPool::Worker(int ID) +{ + std::cout << "ThreadPool::Worker Start -> " << ID << std::endl; + while (isRunning) + { + Fun_Type task = nullptr; + { + CTL::AutoLock lock(m_Mutex); + if (m_TaskQueue.empty()) + { + Thread::SleepMS(5); + continue; + } + task = m_TaskQueue.front(); + m_TaskQueue.pop(); + } + if (task) + { + try + { + task(); + } + catch (const std::exception&) + { + } + task = nullptr; + } + } + std::cout << "ThreadPool::Worker End -> " << ID << std::endl; +} \ No newline at end of file diff --git a/CC_SDK_VS/CCThreadPool.h b/CC_SDK_VS/CCThreadPool.h new file mode 100755 index 0000000..8607f08 --- /dev/null +++ b/CC_SDK_VS/CCThreadPool.h @@ -0,0 +1,42 @@ +#pragma once +#include "CCThread.h" +#include "CCMutex.h" +#include "vector" +#include "queue" +#include "iostream" +#include // Ìí¼Ó´ËÐÐ + +namespace CTL { + class ThreadPool + { + using Fun_Type = std::function; // ÐèҪȷ±£std::function¿ÉÓà + struct TaskBase + { + int ID = -1; + bool IsRunning = false; + Thread* thread_t = nullptr; + }; + public: + ThreadPool(); + ~ThreadPool(); + bool InitStart(int Core); + void Stop(); + template + void AddTask(FUN&& fun, ARGS&& ...Args); + private: + std::queue m_TaskQueue{}; + std::vector m_Threads{}; + CTL::Mutex m_Mutex; + bool isRunning = true; + int M_Core = 10; + void Worker(int ID); + }; + + template + inline void ThreadPool::AddTask(FUN&& fun, ARGS&& ...Args) + { + CTL::AutoLock lock(m_Mutex); + auto task = std::bind(std::forward(fun), std::forward(Args)...); + m_TaskQueue.push(task); + } +} \ No newline at end of file diff --git a/CC_SDK_VS/Socket/CCClientSocket.cpp b/CC_SDK_VS/Socket/CCClientSocket.cpp new file mode 100644 index 0000000..c559e67 --- /dev/null +++ b/CC_SDK_VS/Socket/CCClientSocket.cpp @@ -0,0 +1,164 @@ +#include "CCClientSocket.h" +#include "../CCThread.h" + +CTL::SocketInputStream::SocketInputStream(Socket *sock) { + this->socket = sock; +} + +int CTL::SocketInputStream::read(char *buffer, const size_t length) const { + if (this->socket) { + return this->socket->RecvData(buffer, length); + } + return -1; +} + +int CTL::SocketInputStream::read() const { + char buffer[1] = {}; + const int ret = read(buffer, 1); + if (ret > 0) { + return buffer[0]; + } + return -1; +} + +int CTL::SocketInputStream::read(ByteArray &buffer, const size_t length) const { + if (this->socket) { + buffer.resize(length); + const auto ret = this->socket->RecvData(buffer.buffer(), length); + return ret > 0 ? ret : -1; + } + return -1; +} + +bool CTL::SocketInputStream::available() const { + if (this->socket) { + return this->socket->isDataAvailable(); + } + return false; +} + +CTL::SocketOutputStream::SocketOutputStream(Socket *sock) { + this->socket = sock; +} + +int CTL::SocketOutputStream::write(const void *buffer, const size_t length) const { + if (this->socket) { + while (!CTL::Socket::IsSocketWritable(socket->Socketbit)) { + CTL::Thread::SleepMS(5); + } + int ret = 0; + this->socket->SendByte(static_cast(buffer),length,&ret); + return ret; + } + return false; +} + +bool CTL::SocketOutputStream::write(ByteArray &buffer) const { + if (this->socket) { + return this->socket->SendByte(buffer.buffer(),buffer.size()); + } + return false; +} + +bool CTL::SocketOutputStream::write(const std::string &str) const { + if (this->socket) { + return this->socket->SendByte(str.data(),str.size()); + } + return false; +} + +CTL::ClientSocket::ClientSocket(){ + socket = new Socket(); + this->isConnect_t = true; + this->isClosed_t = false; + IP_x = IPVX::IPV4; + inputStream = NULL; + outputStream = NULL; + Port = 0; +} + +CTL::ClientSocket::~ClientSocket() { + if (inputStream) { + delete inputStream; + inputStream = NULL; + } + if (outputStream) { + delete outputStream; + inputStream = NULL; + } + if (socket) { + delete socket; + socket = NULL; + } + this->isConnect_t = false; + this->isClosed_t = true; +} + +CTL::ClientSocket::ClientSocket(const InetAddress &address, const int Port) { + socket = new Socket(); + connect(address, Port); +} + +CTL::ClientSocket::ClientSocket(Socket *sock) { + this->socket = sock; + this->inputStream = new SocketInputStream(this->socket); + this->outputStream = new SocketOutputStream(this->socket); + this->isConnect_t = true; + this->isClosed_t = false; + const auto addr = socket->GetClientHost(); + this->hostAddress = addr.IPAddress; + this->Port = addr.Port; +} + +bool CTL::ClientSocket::connect(const InetAddress &address, const int Port) { + if (socket) { + this->IP_x = address.getIPx(); + this->Port = Port; + this->hostAddress = address.getHostAddress(); + socket->Init(IP_x, TORU::TCP, TYPE::STREAM); + this->isConnect_t = socket->Connect(hostAddress.c_str(), Port); + if (this->isConnect_t) { + this->isClosed_t = false; + this->inputStream = new SocketInputStream(this->socket); + this->outputStream = new SocketOutputStream(this->socket); + } + return this->isConnect_t; + } + return false; +} + +void CTL::ClientSocket::close() { + if (socket) { + this->isClosed_t = true; + this->isConnect_t = false; + socket->Close(); + } +} + +bool CTL::ClientSocket::isConnect() const { + return this->isConnect_t; +} + +bool CTL::ClientSocket::isClosed() const { + return this->isClosed_t; +} + +CTL::SocketInputStream * CTL::ClientSocket::getInputStream() const { + return this->inputStream; +} + +CTL::SocketOutputStream * CTL::ClientSocket::getOutputStream() const { + return this->outputStream; +} + +CTL::Socket * CTL::ClientSocket::getSocket() const { + return this->socket; +} + +int CTL::ClientSocket::getPort() const { + return this->Port; +} + +CTL::InetAddress CTL::ClientSocket::getHostAddress() const { + return InetAddress(hostAddress); +} diff --git a/CC_SDK_VS/Socket/CCClientSocket.h b/CC_SDK_VS/Socket/CCClientSocket.h new file mode 100644 index 0000000..6566a57 --- /dev/null +++ b/CC_SDK_VS/Socket/CCClientSocket.h @@ -0,0 +1,52 @@ +#ifndef CLIENT_SOCKET_H +#define CLIENT_SOCKET_H + +#include "CCSocket.h" +#include "../base/CCByteArray.h" + +namespace CTL { + class SocketInputStream { + Socket* socket; + public: + explicit SocketInputStream(Socket* sock); + int read(char* buffer, size_t length) const; + int read() const; + int read(ByteArray& buffer, size_t length) const; + bool available() const; + }; + class SocketOutputStream { + Socket* socket; + public: + explicit SocketOutputStream(Socket* sock); + int write(const void* buffer, size_t length) const; + bool write(ByteArray& buffer) const; + bool write(const std::string& str) const; + }; + class ClientSocket { + Socket* socket; + SocketInputStream* inputStream; + SocketOutputStream* outputStream; + IPVX IP_x; + std::string hostAddress; + bool isClosed_t, isConnect_t; + int Port; + public: + private: + public: + ClientSocket(); + ~ClientSocket(); + ClientSocket(const InetAddress& address,int Port); + explicit ClientSocket(Socket* sock); + bool connect(const InetAddress& address,int Port); + void close(); + bool isConnect() const; + bool isClosed() const; + SocketInputStream* getInputStream() const; + SocketOutputStream* getOutputStream() const; + Socket* getSocket() const; + int getPort() const; + InetAddress getHostAddress() const; + }; +} + +#endif diff --git a/CC_SDK_VS/Socket/CCDatagramSocket.cpp b/CC_SDK_VS/Socket/CCDatagramSocket.cpp new file mode 100644 index 0000000..9f6fc98 --- /dev/null +++ b/CC_SDK_VS/Socket/CCDatagramSocket.cpp @@ -0,0 +1,195 @@ +#include "CCDatagramSocket.h" + +CTL::DatagramPacket::DatagramPacket() { + dataBuffer.resize(1440); +} + +CTL::DatagramPacket::DatagramPacket(const size_t length) { + dataBuffer.resize(length); +} + +CTL::DatagramPacket::DatagramPacket(const char *data, const size_t length, const InetAddress &addr, const int portNum) { + dataBuffer.resize(length); + packetLength = length; + address = addr; + port = portNum; + std::memcpy(dataBuffer.buffer(), data, length); +} + +const char* CTL::DatagramPacket::getData() const { + return dataBuffer.buffer(); +} + +size_t CTL::DatagramPacket::getLength() const { + return packetLength; +} + +void CTL::DatagramPacket::setLength(const size_t length) { + if (length <= dataBuffer.size()) { + packetLength = length; + } +} + +size_t CTL::DatagramPacket::getCapacity() const { + return dataBuffer.size(); +} + +CTL::InetAddress CTL::DatagramPacket::getAddress() const { + return address; +} + +void CTL::DatagramPacket::setAddress(const InetAddress &addr) { + address = addr; +} + +int CTL::DatagramPacket::getPort() const { + return port; +} + +void CTL::DatagramPacket::setPort(const int portNum) { + port = portNum; +} + +void CTL::DatagramPacket::setData(const char *data, const size_t length) { + if (length > dataBuffer.size()) { + dataBuffer.resize(length); + } + std::memcpy(dataBuffer.buffer(), data, length); + packetLength = length; +} + +void CTL::DatagramPacket::setData(const ByteArray &data) { + if (data.size() > dataBuffer.size()) { + dataBuffer.resize(data.size()); + } + dataBuffer = data; + packetLength = data.size(); +} + +void CTL::DatagramPacket::reset() { + packetLength = 0; + port = 0; + address = InetAddress(); +} + +std::string CTL::DatagramPacket::getDataAsString() const { + return dataBuffer.toString(); +} + +CTL::ByteArray CTL::DatagramPacket::getDataAsByteArray() const { + return dataBuffer; +} + +bool CTL::DatagramSocket::Init(const int Port, const InetAddress &address) { + socket = new Socket(); + return bind(Port,address); +} + +CTL::DatagramSocket::DatagramSocket() { + socket = new Socket(); + IP_x = IPV4; + isClosed_t = true; + isBound_t = false; + Port = 0; +} + +CTL::DatagramSocket::DatagramSocket(const int Port, const InetAddress &address) { + Init(Port,address); +} + +CTL::DatagramSocket::~DatagramSocket() { + socket->Close(); + delete socket; + socket = NULL; +} + +bool CTL::DatagramSocket::bind(const int Port, const InetAddress &address) { + if (socket) { + this->IP_x = address.getIPx(); + this->Port = Port; + this->hostAddress = address.getHostAddress(); + socket->Init(IP_x, TORU::UDP, TYPE::DGRAM); + this->isBound_t = socket->Bind(hostAddress.c_str(), Port); + if (this->isBound_t) { + this->isClosed_t = false; + } + return this->isBound_t; + } + return false; +} + +bool CTL::DatagramSocket::send(const DatagramPacket &packet) const { + const auto buffer = packet.getDataAsByteArray(); + const auto size = packet.getLength(); + const auto addr = packet.getAddress(); + const auto port = packet.getPort(); + return socket->UDPSendByte(buffer.buffer(),size,addr.getHostName().c_str(),port); +} + +void CTL::DatagramSocket::receive(DatagramPacket &packet) const { + if (socket) { + ByteArray buffer; + const auto size = packet.getCapacity(); + buffer.resize(size); + CCHostInfo info; + const auto len = socket->UDPRecvData(buffer.buffer(),size,&info); + if (len > 0) { + const InetAddress address(info.IPAddress); + packet.setAddress(address); + packet.setPort(info.Port); + packet.setData(buffer.subBuffer(0,len)); + packet.setLength(len); + } + } +} + +void CTL::DatagramSocket::close() { + if (socket) { + this->isClosed_t = true; + this->isBound_t = false; + socket->Close(); + } +} + +bool CTL::DatagramSocket::isBound() const { + return this->isBound_t; +} + +bool CTL::DatagramSocket::isClosed() const { + return this->isClosed_t; +} + +int CTL::DatagramSocket::getLocalPort() const { + return this->Port; +} + +CTL::InetAddress CTL::DatagramSocket::getLocalAddress() const { + InetAddress address(this->IP_x, this->hostAddress); + return address; +} + +bool CTL::DatagramSocket::available() const { + if (socket) { + return socket->isDataAvailable(); + } + return false; +} + +CTL::Socket * CTL::DatagramSocket::getSocket() const { + return socket; +} + +void CTL::DatagramSocket::broadcast(const DatagramPacket& packet) const{ + if (socket){ + sockaddr_in serverAddr = {}; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(packet.getPort()); + serverAddr.sin_addr.s_addr = INADDR_BROADCAST; + socket->SendData(packet.getData(),packet.getLength(),serverAddr); + } +} + +bool CTL::DatagramSocket::setSockOpt(const CCOpt opt) const { + return socket->SetSockOpt(opt); +} + diff --git a/CC_SDK_VS/Socket/CCDatagramSocket.h b/CC_SDK_VS/Socket/CCDatagramSocket.h new file mode 100644 index 0000000..2726043 --- /dev/null +++ b/CC_SDK_VS/Socket/CCDatagramSocket.h @@ -0,0 +1,92 @@ +#ifndef DATAGRAM_SOCKET_H +#define DATAGRAM_SOCKET_H + +#include + +#include "CCSocket.h" +#include "../base/CCByteArray.h" + +namespace CTL { + class DatagramPacket { + ByteArray dataBuffer; + size_t packetLength = 0; + InetAddress address; + int port = 0; + public: + // 构造函数:创建用于接收数æ®åŒ…的对象 + DatagramPacket(); + // 构造函数:创建用于接收数æ®åŒ…的对象 + explicit DatagramPacket(size_t length); + // 构造函数:创建用于å‘逿•°æ®åŒ…的对象 + DatagramPacket(const char* data, size_t length, const InetAddress& addr, int portNum); + // 构造函数:创建用于å‘逿•°æ®åŒ…的对象(使用vector) + DatagramPacket(const ByteArray& data, InetAddress addr, const int portNum) + : dataBuffer(data), packetLength(data.size()), address(addr), port(portNum) {} + // èŽ·å–æ•°æ®ç¼“冲区(const版本) + [[nodiscard]] const char* getData() const; + // èŽ·å–æ•°æ®ç¼“冲区长度 + [[nodiscard]] size_t getLength() const; + // 设置数æ®é•¿åº¦ + void setLength(size_t length); + // 获å–ç¼“å†²åŒºå®¹é‡ + [[nodiscard]] size_t getCapacity() const; + // 获å–ç›®æ ‡åœ°å€ + [[nodiscard]] InetAddress getAddress() const; + // è®¾ç½®ç›®æ ‡åœ°å€ + void setAddress(const InetAddress& addr); + // 获å–ç›®æ ‡ç«¯å£ + [[nodiscard]] int getPort() const; + // è®¾ç½®ç›®æ ‡ç«¯å£ + void setPort(int portNum); + // 设置数æ®ï¼ˆä»Žå­—符数组) + void setData(const char* data, size_t length); + // 设置数æ®ï¼ˆä»Žvector) + void setData(const ByteArray& data); + // é‡ç½®æ•°æ®åŒ…(清空内容) + void reset(); + // èŽ·å–æ•°æ®ä¸ºå­—ç¬¦ä¸²ï¼ˆå¦‚æžœæ•°æ®æ˜¯æ–‡æœ¬ï¼‰ + [[nodiscard]] std::string getDataAsString() const; + // èŽ·å–æ•°æ®ä¸ºå­—节数组 + [[nodiscard]] ByteArray getDataAsByteArray() const; + }; + class DatagramSocket { + Socket* socket; + IPVX IP_x; + std::string hostAddress; + bool isClosed_t, isBound_t; + int Port; + bool Init(int Port, const InetAddress &address); + public: + DatagramSocket(); + explicit DatagramSocket(int Port, const InetAddress &address = InetAddress::getAnyAddress()); + ~DatagramSocket(); + // 绑定到特定地å€å’Œç«¯å£ + bool bind(int Port, const InetAddress &address = InetAddress::getAnyAddress()); + // å‘逿•°æ®åŒ… + [[nodiscard]] bool send(const DatagramPacket& packet) const; + // 接收数æ®åŒ… + void receive(DatagramPacket& packet) const; + // 关闭套接字 + void close(); + // 检查套接字是å¦å·²ç»‘定 + [[nodiscard]] bool isBound() const; + // 检查套接字是å¦å·²å…³é—­ + [[nodiscard]] bool isClosed() const; + // èŽ·å–æœ¬åœ°ç«¯å£ + [[nodiscard]] int getLocalPort() const; + // èŽ·å–æœ¬åœ°åœ°å€ + [[nodiscard]] InetAddress getLocalAddress() const; + // æ˜¯å¦æœ‰æ•°æ®å¯è¯» + [[nodiscard]] bool available() const; + // 获å–Socket + [[nodiscard]] Socket* getSocket() const; + // 广播数æ®åŒ… + void broadcast(const DatagramPacket& packet) const; + // è®¾ç½®å‚æ•° + bool setSockOpt(CCOpt opt) const; + }; +} + + + +#endif diff --git a/CC_SDK_VS/Socket/CCServerSocket.cpp b/CC_SDK_VS/Socket/CCServerSocket.cpp new file mode 100644 index 0000000..6ef0fc6 --- /dev/null +++ b/CC_SDK_VS/Socket/CCServerSocket.cpp @@ -0,0 +1,78 @@ +#include "CCServerSocket.h" + +bool CTL::ServerSocket::Init(const int Port, const InetAddress &address) { + socket = new Socket(); + return bind(Port,address); +} + +CTL::ServerSocket::ServerSocket() { + socket = new Socket(); + IP_x = IPVX::IPV4; + isClosed_t = true; + isBound_t = false; + isListen_t = false; + Port = 0; +} + +CTL::ServerSocket::~ServerSocket() { + delete socket; +} + +CTL::ServerSocket::ServerSocket(const int Port, const InetAddress &address) { + Init(Port,address); +} + +bool CTL::ServerSocket::bind(const int Port, const InetAddress &address) { + if (socket) { + this->IP_x = address.getIPx(); + this->Port = Port; + this->hostAddress = address.getHostAddress(); + socket->Init(IP_x, TORU::TCP, TYPE::STREAM); + this->isBound_t = socket->Bind(hostAddress.c_str(), Port); + if (this->isBound_t) { + this->isClosed_t = false; + } + return this->isBound_t; + } + return false; +} + +bool CTL::ServerSocket::listen(const int backlog){ + if (socket) { + this->isListen_t = socket->Listen(backlog); + if (this->isListen_t) { + this->isClosed_t = false; + this->isListen_t = true; + } + return this->isListen_t; + } + return false; +} + +void CTL::ServerSocket::close() { + if (socket) { + this->isClosed_t = true; + this->isBound_t = false; + socket->Close(); + } +} + +bool CTL::ServerSocket::isBound() const { + return this->isBound_t; +} + +bool CTL::ServerSocket::isClosed() const { + return this->isClosed_t; +} + +CTL::Socket * CTL::ServerSocket::getSocket() const { + return this->socket; +} + +CTL::ClientSocket * CTL::ServerSocket::accept() const { + if (!this->isListen_t) { + throw std::runtime_error("ServerSocket::accept() error: ServerSocket is not listening."); + } + const auto clientSocket = new Socket(socket->Accept()); + return new ClientSocket(clientSocket); +} diff --git a/CC_SDK_VS/Socket/CCServerSocket.h b/CC_SDK_VS/Socket/CCServerSocket.h new file mode 100644 index 0000000..8a087db --- /dev/null +++ b/CC_SDK_VS/Socket/CCServerSocket.h @@ -0,0 +1,32 @@ +#ifndef SERVER_SOCKET_H +#define SERVER_SOCKET_H + +#include "CCSocket.h" +#include "CCClientSocket.h" + +namespace CTL { + class ServerSocket { + Socket* socket; + IPVX IP_x; + std::string hostAddress; + bool isClosed_t, isBound_t,isListen_t; + int Port; + public: + private: + bool Init(int Port,const InetAddress& address); + public: + ServerSocket(); + ~ServerSocket(); + explicit ServerSocket(int Port, const InetAddress &address = InetAddress::getAnyAddress()); + bool bind(int Port,const InetAddress& address = InetAddress::getAnyAddress()); + bool listen(int backlog = 50); + void close(); + bool isBound() const; + bool isClosed() const; + Socket* getSocket() const; + ClientSocket* accept() const; + }; +} + + +#endif diff --git a/CC_SDK_VS/Socket/CCSocket.cpp b/CC_SDK_VS/Socket/CCSocket.cpp new file mode 100644 index 0000000..3c3df0b --- /dev/null +++ b/CC_SDK_VS/Socket/CCSocket.cpp @@ -0,0 +1,1183 @@ +#include "CCSocket.h" + +#include +#include +#include + +using namespace CTL; + +Socket::Socket() { + sock = -1; + IPVx = IPVX::IPV4; + Stop = false; + opt = -1; +} + +CTL::Socket::Socket(const SOCKET sock) { + Socketbit = sock; + IPVx = IPVX::IPV4; + Stop = false; + opt = -1; +} + +bool CTL::Socket::Init(IPVX IPV4orIPV6, TORU TCPorUDP, TYPE Type){ +#ifdef _WIN32 + CTL::Socket sc{}; + this->Socketbit = socket(IPV4orIPV6, TCPorUDP == TCP ? SOCK_STREAM : SOCK_DGRAM, TCPorUDP); + if (this->Socketbit == INVALID_SOCKET){ + return false; + } + this->sock = TCPorUDP; + this->IPVx = IPV4orIPV6; + sc.sock = this->sock; + sc.IPVx = this->IPVx; + sc.Socketbit = this->Socketbit; + return true; +#elif __linux__ + CTL::Socket sc; + Socketbit = socket(IPV4orIPV6, Type, TCPorUDP); + if(Socketbit == 0) + { + Socketbit = -1; + return false; + } + int err = setsockopt(Socketbit, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + if(!err){ + err = setsockopt(Socketbit, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)); + } + if(err) + { + Socketbit = -2; + return false; + } + this->IPVx = IPV4orIPV6; + sc.IPVx = this->IPVx; + sc.Socketbit = Socketbit; + return true; +#endif +} + +SOCKET CTL::Socket::GetSOCKET() const { + return Socketbit; +} + +bool CTL::Socket::SetSockOpt(CCOpt opt) const { +#ifdef _WIN32 + switch(opt) { + case CCOpt::BROADCAST: + { + int broadcastPermission = 1; + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_BROADCAST, + (const char*)&broadcastPermission, sizeof(broadcastPermission)) < 0) { + return false; + } + break; + } + case CCOpt::REUSEADDR: + { + int reuseAddr = 1; + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_REUSEADDR, + (const char*)&reuseAddr, sizeof(reuseAddr)) < 0) { + return false; + } + break; + } +#ifdef SO_REUSEPORT + case CCOpt::REUSEPORT: + { + int reusePort = 1; + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_REUSEPORT, + (const char*)&reusePort, sizeof(reusePort)) < 0) { + return false; + } + break; + } +#endif + case CCOpt::NOBLOCK: + { + u_long mode = 1; + if (ioctlsocket(this->Socketbit, FIONBIO, &mode) == SOCKET_ERROR) { + return false; + } + break; + } + case CCOpt::LINGER_t: + { + linger l = {1, 0}; // l_onoff=1, l_linger=0 + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_LINGER, + (const char*)&l, sizeof(l)) < 0) { + return false; + } + break; + } + case CCOpt::SNDBUF: + { + int bufferSize = 65536; // 默认å‘é€ç¼“å†²åŒºå¤§å° + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_SNDBUF, + (const char*)&bufferSize, sizeof(bufferSize)) < 0) { + return false; + } + break; + } + case CCOpt::RCVBUF: + { + int bufferSize = 65536; // é»˜è®¤æŽ¥æ”¶ç¼“å†²åŒºå¤§å° + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_RCVBUF, + (const char*)&bufferSize, sizeof(bufferSize)) < 0) { + return false; + } + break; + } + case CCOpt::TIMESTAMP: + { +#ifdef SO_TIMESTAMP + int timestamp = 1; + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_TIMESTAMP, + (const char*)×tamp, sizeof(timestamp)) < 0) { + return false; + } +#endif + break; + } + default: + return false; + } + return true; +#elif __linux__ + switch(opt) { + case CCOpt::BROADCAST: + { + int broadcastPermission = 1; + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_BROADCAST, + (const char*)&broadcastPermission, sizeof(broadcastPermission)) < 0) { + return false; + } + break; + } + case CCOpt::REUSEADDR: + { + int reuseAddr = 1; + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_REUSEADDR, + (const char*)&reuseAddr, sizeof(reuseAddr)) < 0) { + return false; + } + break; + } + case CCOpt::REUSEPORT: + { + int reusePort = 1; + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_REUSEPORT, + (const char*)&reusePort, sizeof(reusePort)) < 0) { + return false; + } + break; + } + case CCOpt::NOBLOCK: + { + int flags = fcntl(this->Socketbit, F_GETFL, 0); + if (flags == -1) return false; + flags |= O_NONBLOCK; + if (fcntl(this->Socketbit, F_SETFL, flags) == -1) { + return false; + } + break; + } + case CCOpt::LINGER_t: + { + struct linger l = {1, 0}; // l_onoff=1, l_linger=0 + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_LINGER, + (const char*)&l, sizeof(l)) < 0) { + return false; + } + break; + } + case CCOpt::SNDBUF: + { + int bufferSize = 65536; // 默认å‘é€ç¼“å†²åŒºå¤§å° + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_SNDBUF, + (const char*)&bufferSize, sizeof(bufferSize)) < 0) { + return false; + } + break; + } + case CCOpt::RCVBUF: + { + int bufferSize = 65536; // é»˜è®¤æŽ¥æ”¶ç¼“å†²åŒºå¤§å° + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_RCVBUF, + (const char*)&bufferSize, sizeof(bufferSize)) < 0) { + return false; + } + break; + } + case CCOpt::TIMESTAMP: + { +#ifdef SO_TIMESTAMP + int timestamp = 1; + if (setsockopt(this->Socketbit, SOL_SOCKET, SO_TIMESTAMP, + (const char*)×tamp, sizeof(timestamp)) < 0) { + return false; + } +#endif + break; + } + default: + return false; + } + return true; +#endif +} + +std::vector CTL::Socket::GetLocalIP(IPVX ipvx,int Number) +{ +#ifdef _WIN32 + std::vector IPList; + int result = 0; + // 获å–主机å + char hostName[NI_MAXHOST]; + if (gethostname(hostName, NI_MAXHOST) != 0) { + std::cerr << "gethostname failed" << std::endl; + WSACleanup(); + return {}; + } + struct addrinfo hints, *info; + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_UNSPEC; // AF_INET for IPv4 only + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + // 获å–地å€ä¿¡æ¯ + result = getaddrinfo(hostName, NULL, &hints, &info); + if (result != 0) { + std::cerr << "getaddrinfo failed: " << result << std::endl; + return {}; + } + char ipString[INET6_ADDRSTRLEN] = {0}; + // é历所有地å€ä¿¡æ¯å¹¶æ‰“å°IPv4åœ°å€ + for (struct addrinfo* p = info; p != NULL; p = p->ai_next) { + void* addr; + + // 对于IPv4,使用ipv4_mappingæ¥å…¼å®¹IPv6åœ°å€ + if (p->ai_family == ipvx) { + if (p->ai_family == IPV4) { + const sockaddr_in * ipv4 = reinterpret_cast(p->ai_addr); + addr = &(ipv4->sin_addr); + } + else if (p->ai_family == IPV6) { + sockaddr_in6 * ipv6 = reinterpret_cast(p->ai_addr); + addr = &(ipv6->sin6_addr); + } + else { + continue; + } + } + else { + continue; + } + // 将地å€è½¬æ¢ä¸ºå­—符串 + inet_ntop(p->ai_family, addr, ipString, sizeof(ipString)); + IPList.emplace_back(ipString); + // std::cout << "IPv4 address: " << ipString << std::endl; + } + // 释放地å€ä¿¡æ¯ + freeaddrinfo(info); + return IPList; +#elif __linux__ + std::vector IPList; + struct ifaddrs *ifAddrStruct = NULL; + struct ifaddrs *ifa = NULL; + void *tmpAddrPtr = NULL; + + getifaddrs(&ifAddrStruct); + char addressBuffer[10][INET_ADDRSTRLEN] = {0}; + int d = 0; + for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr->sa_family == ipvx) { // 检查它是å¦ä¸ºIPv4 + if (ifa->ifa_addr->sa_family == IPV4) { + // èŽ·å–æŽ¥å£åœ°å€ + tmpAddrPtr = &reinterpret_cast(ifa->ifa_addr)->sin_addr; + } + else if (ifa->ifa_addr->sa_family == IPV6) { + // èŽ·å–æŽ¥å£åœ°å€ + tmpAddrPtr = &reinterpret_cast(ifa->ifa_addr)->sin6_addr; + } + inet_ntop(ifa->ifa_addr->sa_family, tmpAddrPtr, addressBuffer[d++], INET_ADDRSTRLEN); + IPList.push_back(addressBuffer[d-1]); + } + } + + if (ifAddrStruct != NULL) + freeifaddrs(ifAddrStruct); + return IPList; +#endif + +} + +bool CTL::Socket::Connect(const char* IP, unsigned short Port) { +#ifdef _WIN32 + Stop = true; + if (this->IPVx == IPV4) { + server.sin_family = AF_INET; + server.sin_port = htons(Port); + server.sin_addr.s_addr = inet_addr(IP); + if (server.sin_addr.s_addr == INADDR_NONE) { + // å¦‚æžœä¸æ˜¯æœ‰æ•ˆIP地å€ï¼Œå°è¯•DNSè§£æž + struct addrinfo hints = {}, *result = NULL; + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + if (getaddrinfo(IP, NULL, &hints, &result) != 0) { + std::cerr << "DNS resolution failed for: " << IP << std::endl; + return false; + } + + const sockaddr_in* addr_in = reinterpret_cast(result->ai_addr); + server.sin_addr = addr_in->sin_addr; + freeaddrinfo(result); + } + int len = sizeof(server); + int i = connect(this->Socketbit,reinterpret_cast(&server),len); + if (i == SOCKET_ERROR){ + return false; + } + } + else if (this->IPVx == IPV6) { + server_6.sin6_family = AF_INET6; + server_6.sin6_port = htons(Port); + if (inet_pton(AF_INET6, IP, &server_6.sin6_addr) != 1) { + // å¦‚æžœä¸æ˜¯æœ‰æ•ˆ IPv6 地å€ï¼Œå°è¯• DNS è§£æž + struct addrinfo hints = {}, *result = NULL; + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; + + if (getaddrinfo(IP, NULL, &hints, &result) != 0) { + std::cerr << "DNS resolution failed for: " << IP << std::endl; + return false; + } + + // ç¡®ä¿èŽ·å–到的是 IPv6 åœ°å€ + if (result->ai_family != AF_INET6) { + std::cerr << "DNS resolution did not return IPv6 address for: " << IP << std::endl; + freeaddrinfo(result); + return false; + } + + const sockaddr_in6* addr_in6 = reinterpret_cast(result->ai_addr); + server_6.sin6_addr = addr_in6->sin6_addr; + freeaddrinfo(result); + } + int len = sizeof(sockaddr_in6); + int i = connect(this->Socketbit,reinterpret_cast(&server_6),len); + if (i == SOCKET_ERROR){ + return false; + } + } + return true; +#elif __linux__ + Stop = true; + if (this->IPVx == IPV4) { + server.sin_family = AF_INET; + server.sin_port = htons(Port); + server.sin_addr.s_addr = inet_addr(IP); + if (server.sin_addr.s_addr == INADDR_NONE) { + // å¦‚æžœä¸æ˜¯æœ‰æ•ˆIP地å€ï¼Œå°è¯•DNSè§£æž + struct addrinfo hints = {}, *result = NULL; + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + if (getaddrinfo(IP, NULL, &hints, &result) != 0) { + std::cerr << "DNS resolution failed for: " << IP << std::endl; + return false; + } + + const sockaddr_in* addr_in = reinterpret_cast(result->ai_addr); + server.sin_addr = addr_in->sin_addr; + freeaddrinfo(result); + } + int len = sizeof(server); + int i = connect(this->Socketbit,(sockaddr*)&server,len); + if (i == SOCKET_ERROR){ + return false; + } + } + else if (this->IPVx == IPV6) { + server_6.sin6_family = AF_INET6; + server_6.sin6_port = htons(Port); + if (inet_pton(AF_INET6, IP, &server_6.sin6_addr) != 1) { + // å¦‚æžœä¸æ˜¯æœ‰æ•ˆ IPv6 地å€ï¼Œå°è¯• DNS è§£æž + struct addrinfo hints = {}, *result = NULL; + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_STREAM; + + if (getaddrinfo(IP, NULL, &hints, &result) != 0) { + std::cerr << "DNS resolution failed for: " << IP << std::endl; + return false; + } + + // ç¡®ä¿èŽ·å–到的是 IPv6 åœ°å€ + if (result->ai_family != AF_INET6) { + std::cerr << "DNS resolution did not return IPv6 address for: " << IP << std::endl; + freeaddrinfo(result); + return false; + } + + const sockaddr_in6* addr_in6 = reinterpret_cast(result->ai_addr); + server_6.sin6_addr = addr_in6->sin6_addr; + freeaddrinfo(result); + } + int len = sizeof(sockaddr_in6); + int i = connect(this->Socketbit,reinterpret_cast(&server_6),len); + if (i == SOCKET_ERROR){ + return false; + } + } + return true; +#endif +} + +bool CTL::Socket::Bind(const char* IP, unsigned short Port){ +#ifdef _WIN32 + if (IPVx == IPV4) { + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_port = htons(Port); + server.sin_addr.s_addr = inet_addr(IP); + int i = bind(this->Socketbit, reinterpret_cast(&server), sizeof(server)); + if (i == SOCKET_ERROR){ + int error = WSAGetLastError(); + std::cerr << " failed with error: " << error << std::endl; + this->Socketbit = -1; + closesocket(this->Socketbit); + return false; + } + } + else if (IPVx == IPV6) { + constexpr int len = sizeof(sockaddr_in6); // "fe80:0:0:0:f73c:715:87e5:14b1" + memset(&server_6, 0, len); + server_6.sin6_family = AF_INET6; + server_6.sin6_port = htons(Port); + if (inet_pton(AF_INET6, IP, &server_6.sin6_addr) != 1) { + std::cerr << "Invalid IPv6 address: " << IP << std::endl; + return false; + } + const sockaddr * s = reinterpret_cast(&server_6); + if (const int i = bind(this->Socketbit,s , len); i == SOCKET_ERROR){ + const int error = WSAGetLastError(); + std::cerr << " failed with error: " << error << std::endl; + this->Socketbit = -1; + closesocket(this->Socketbit); + return false; + } + } + return true; +#elif __linux__ + if (IPVx == IPV4) { + // 设置地å€ç»“æž„ + memset(&server, 0, sizeof(server)); + server.sin_family = IPVx; + server.sin_port = htons(Port); + server.sin_addr.s_addr = inet_addr(IP); + // 绑定套接字到地å€å’Œç«¯å£ + if (bind(this->Socketbit, (struct sockaddr *)&server, sizeof(server)) < 0) { + std::cerr << "Bind failed" << std::endl; + return false; + } + } + else if (IPVx == IPV6) { + memset(&server_6, 0, sizeof(sockaddr_in6)); + server_6.sin6_family = AF_INET6; + server_6.sin6_port = htons(Port); + inet_pton(AF_INET6, IP, &server_6.sin6_addr); + const int len = sizeof(sockaddr_in6); + const sockaddr * s = reinterpret_cast(&server_6); + const int i = bind(this->Socketbit,s , len); + if (i < 0){ + std::cerr << "Bind failed" << std::endl; + return false; + } + } + return true; +#endif +} + +bool CTL::Socket::Listen(unsigned short UserNum) +{ +#ifdef _WIN32 + Stop = true; + int iLisRet = listen(this->Socketbit, UserNum); + if (iLisRet == SOCKET_ERROR){ + closesocket(this->Socketbit); + return false; + } + return true; +#elif __linux__ + Stop = true; + int err = listen(Socketbit, UserNum); + if(err < 0) + { + return false; + } + return true; +#endif +} + +CTL::Socket CTL::Socket::Accept() const { +#ifdef _WIN32 + CTL::Socket sc; + if (this->IPVx == IPV4) { + SOCKADDR_IN serveraddrfrom{}; + int Len = sizeof(serveraddrfrom); + SOCKET s = accept(this->Socketbit, reinterpret_cast(&serveraddrfrom), &Len); + sc.Socketbit = s; + sc.sock = this->sock; + sc.client = serveraddrfrom; + } + else if (this->IPVx == IPV6) { + sockaddr_in6 addrClient = {};// ä¿å­˜å®¢æˆ·ç«¯IP地å€ç«¯å£ + int len = sizeof(sockaddr_in6);//地å€ç»“æž„å¤§å°æ”¹å˜ sizeof(sockaddr_in6) + SOCKET s = accept(this->Socketbit, reinterpret_cast(&addrClient), &len); + sc.Socketbit = s; + sc.sock = this->sock; + sc.client_6 = addrClient; + } + sc.IPVx = this->IPVx; + return sc; +#elif __linux__ + CTL::Socket sc; + if (this->IPVx == IPV4) { + sockaddr_in serveraddrfrom = {}; + socklen_t Len = sizeof(serveraddrfrom); + SOCKET s = accept(this->Socketbit, reinterpret_cast(&serveraddrfrom), &Len); + sc.Socketbit = s; + sc.sock = this->sock; + sc.client = serveraddrfrom; + } + else if (this->IPVx == IPV6) { + sockaddr_in6 addrClient = {};// ä¿å­˜å®¢æˆ·ç«¯IP地å€ç«¯å£ + socklen_t len = sizeof(sockaddr_in6);//地å€ç»“æž„å¤§å°æ”¹å˜ sizeof(sockaddr_in6) + SOCKET s = accept(this->Socketbit, reinterpret_cast(&addrClient), &len); + sc.Socketbit = s; + sc.sock = this->sock; + sc.client_6 = addrClient; + } + sc.IPVx = this->IPVx; + return sc; +#endif +} + +bool CTL::Socket::Send(const char* str) const { + return SendByte(str, strlen(str)); +} + +bool CTL::Socket::SendByte(const char* str, int len) const { +#ifdef _WIN32 + int ires = send(this->Socketbit, str, len, MSL_N); + if (ires == -1){ + return false; + } + return true; +#elif __linux__ + const int bytesSent = send(Socketbit, str, len, MSL_N); + if(bytesSent == -1){ + return false; + } + return true; +#endif +} + +bool Socket::SendByte(const char *str, int len, int *ret) const { +#ifdef _WIN32 + const int bytesSent = send(Socketbit, str, len, MSL_N); +#elif __linux__ + const int bytesSent = send(Socketbit, str, len, MSL_N); +#endif + if (bytesSent == SOCKET_ERROR) { + // 处ç†å‘é€é”™è¯¯ + const int err = GetLastError(); + if (err == 32) { + *ret = -32; + } + return false; + // æ ¹æ®é”™è¯¯ç å†³å®šæ˜¯å¦é‡è¯• + } + else if (bytesSent < len) { + *ret = bytesSent; + return false; + } + *ret = bytesSent; + return true; +} + +bool CTL::Socket::UDPSend(const char* str, const char* IP, int Port) const { + return UDPSendByte(str, strlen(str), IP, Port); +} + +bool CTL::Socket::UDPSendByte(const char* str,ByteHander len ,const char* IP, int Port) const { +#ifdef _WIN32 + if (this->IPVx == IPV4) { + sockaddr_in serverAddr{}; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(Port); + serverAddr.sin_addr.s_addr = inet_addr(IP); + if (sendto(this->Socketbit, str, len, 0, reinterpret_cast(&serverAddr), + sizeof(serverAddr)) == SOCKET_ERROR){ + return false; + } + } + else if (this->IPVx == IPV6) { + sockaddr_in6 serverAddr{}; + serverAddr.sin6_family = AF_INET6; + serverAddr.sin6_port = htons(Port); + if (inet_pton(AF_INET6, IP, &serverAddr.sin6_addr) != 1) { + std::cerr << "Invalid IPv6 address: " << IP << std::endl; + return false; + } + if (sendto(this->Socketbit, str, len, 0, reinterpret_cast(&serverAddr), + sizeof(serverAddr)) == SOCKET_ERROR){ + return false; + } + } + return true; +#elif __linux__ + if (this->IPVx == IPV4) { + sockaddr_in serverAddr; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(Port); + serverAddr.sin_addr.s_addr = inet_addr(IP); + if (sendto(this->Socketbit, str, len, 0, reinterpret_cast(&serverAddr), + sizeof(serverAddr)) == SOCKET_ERROR){ + return false; + } + } + else if (this->IPVx == IPV6) { + sockaddr_in6 serverAddr; + serverAddr.sin6_family = AF_INET6; + serverAddr.sin6_port = htons(Port); + if (inet_pton(AF_INET6, IP, &serverAddr.sin6_addr) != 1) { + std::cerr << "Invalid IPv6 address: " << IP << std::endl; + return false; + } + if (sendto(this->Socketbit, str, len, 0, reinterpret_cast(&serverAddr), + sizeof(serverAddr)) == SOCKET_ERROR){ + return false; + } + } + return true; +#endif +} + +bool Socket::UDPSendByte(void *str, ByteHander len, const char *IP, int Port) const { +#ifdef _WIN32 + if (this->IPVx == IPV4) { + sockaddr_in serverAddr{}; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(Port); + serverAddr.sin_addr.s_addr = inet_addr(IP); + if (sendto(this->Socketbit, static_cast(str), len, 0, reinterpret_cast(&serverAddr), + sizeof(serverAddr)) == SOCKET_ERROR){ + return false; + } + } + else if (this->IPVx == IPV6) { + sockaddr_in6 serverAddr{}; + serverAddr.sin6_family = AF_INET6; + serverAddr.sin6_port = htons(Port); + if (inet_pton(AF_INET6, IP, &serverAddr.sin6_addr) != 1) { + std::cerr << "Invalid IPv6 address: " << IP << std::endl; + return false; + } + if (sendto(this->Socketbit, static_cast(str), len, 0, reinterpret_cast(&serverAddr), + sizeof(serverAddr)) == SOCKET_ERROR){ + return false; + } + } + return true; +#elif __linux__ + if (this->IPVx == IPV4) { + sockaddr_in serverAddr; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(Port); + serverAddr.sin_addr.s_addr = inet_addr(IP); + if (sendto(this->Socketbit, str, len, 0, reinterpret_cast(&serverAddr), + sizeof(serverAddr)) == SOCKET_ERROR){ + return false; + } + } + else if (this->IPVx == IPV6) { + sockaddr_in6 serverAddr; + serverAddr.sin6_family = AF_INET6; + serverAddr.sin6_port = htons(Port); + if (inet_pton(AF_INET6, IP, &serverAddr.sin6_addr) != 1) { + std::cerr << "Invalid IPv6 address: " << IP << std::endl; + return false; + } + if (sendto(this->Socketbit, str, len, 0, reinterpret_cast(&serverAddr), + sizeof(serverAddr)) == SOCKET_ERROR){ + return false; + } + } + return true; +#endif +} + +ByteHander CTL::Socket::RecvData(char* buffer, const ByteHander lens) const { + const unsigned long len = recv(Socketbit,buffer,lens,0); + if (errno == EAGAIN || errno == EWOULDBLOCK) { + // 没有数æ®å¯è¯»ï¼Œç¨åŽé‡è¯• + return -2; // 或其他表示无数æ®çš„值 + } + return len; +} + +ByteHander CTL::Socket::UDPRecvData(char* buffer, ByteHander lens,CCHostInfo* info) const { +#ifdef _WIN32 + if (this->IPVx == IPV4) { + sockaddr_in A = {}; + int clientSize = sizeof(A); + int bytesReceived = recvfrom(this->Socketbit, buffer, lens, 0,reinterpret_cast(&A), &clientSize); + if (info) { + char IP[INET_ADDRSTRLEN] = {0}; + inet_ntop(IPVx, &A.sin_addr, IP, INET_ADDRSTRLEN); + info->IPAddress = IP; + info->Port = ntohs(A.sin_port); + } + return bytesReceived; + } + else if (this->IPVx == IPV6) { + sockaddr_in6 A = {}; + int clientSize = sizeof(A); + int bytesReceived = recvfrom(this->Socketbit, buffer, lens, 0,reinterpret_cast(&A), &clientSize); + if (info) { + char IP[INET6_ADDRSTRLEN] = {0}; + inet_ntop(IPVx, &A.sin6_addr, IP, INET6_ADDRSTRLEN); + info->IPAddress = IP; + info->Port = ntohs(A.sin6_port); + } + return bytesReceived; + } + return 0; +#elif __linux__ + if (this->IPVx == IPV4) { + sockaddr_in A = {}; + socklen_t clientSize = sizeof(A); + int bytesReceived = recvfrom(this->Socketbit, buffer, lens, 0,reinterpret_cast(&A), &clientSize); + if (info) { + char IP[INET_ADDRSTRLEN] = {0}; + inet_ntop(IPVx, &A.sin_addr, IP, INET_ADDRSTRLEN); + info->IPAddress = IP; + info->Port = ntohs(A.sin_port); + } + return bytesReceived; + } + else if (this->IPVx == IPV6) { + sockaddr_in6 A = {}; + socklen_t clientSize = sizeof(A); + int bytesReceived = recvfrom(this->Socketbit, buffer, lens, 0,reinterpret_cast(&A), &clientSize); + if (info) { + char IP[INET6_ADDRSTRLEN] = {0}; + inet_ntop(IPVx, &A.sin6_addr, IP, INET6_ADDRSTRLEN); + info->IPAddress = IP; + info->Port = ntohs(A.sin6_port); + } + return bytesReceived; + } + return 0; +#endif +} + +void CTL::Socket::Close() +{ +#ifdef _WIN32 + Stop = false; + closesocket(this->Socketbit); + this->Socketbit = -1; +#elif __linux__ + Stop = false; + close(Socketbit); + this->Socketbit = -1; +#endif +} + +bool CTL::Socket::GetDateHead(char* data, ByteHander* size) +{ +#ifdef _WIN32 + int i = sizeof(data); + memcpy(size,data,i); + if (size!=0) + { + return true; + } + return false; +#elif __linux__ + int i = sizeof(data); + memcpy(size,data,i); + if (size!=0) + { + return true; + } + return false; +#endif +} + +bool CTL::Socket::GetStrHead(char* data, ByteHander size) +{ +#ifdef _WIN32 + for (int i = 0; i < HanderSize; i++) + { + data[i] = '\0'; + } + data[0] = '-'; + memcpy(data, &size, sizeof(ByteHander)); + if (data[0] == '-') + { + return false; + } + return true; +#elif __linux__ + for (int i = 0; i < HanderSize; i++) + { + data[i] = '\0'; + } + data[0] = '-'; + memcpy(data, &size, sizeof(ByteHander)); + if (data[0] == '-') + { + return false; + } + return true; +#endif +} + +bool CTL::Socket::Send(const char *__buf, size_t __n, int __flags) const { +#ifdef _WIN32 + int err = send(Socketbit, (char*)__buf, __n, __flags); + if(err == -1) + { + int errorCode = WSAGetLastError(); // Windows + // std::cerr << "Send failed with error code: " << errorCode << std::endl; + // 处ç†é”™è¯¯ç  + return false; + } + return true; +#elif __linux__ + int err = send(Socketbit, __buf, __n, __flags); + if(err == -1) + { + return false; + } + return true; +#endif +} + +bool CTL::Socket::SendData(const char* str,const int length, sockaddr_in addr_in) const { +#ifdef _WIN32 + bool F = sendto(this->Socketbit, str, length, 0, (sockaddr*)&addr_in, sizeof(addr_in)) != SOCKET_ERROR; + return F; +#elif __linux__ + bool F = sendto(this->Socketbit, str, length, 0, (sockaddr*)&addr_in, sizeof(addr_in)) != -1; + return F; +#endif +} + +bool CTL::Socket::operator==(CTL::Socket socket) const { +#ifdef _WIN32 + if(socket.Socketbit == this->Socketbit) + { + return true; + } + return false; +#elif __linux__ + if(socket.Socketbit == this->Socketbit) + { + return true; + } + return false; +#endif +} + +bool CTL::Socket::operator!=(CTL::Socket socket) const { +#ifdef _WIN32 + if(socket.Socketbit != this->Socketbit) + { + return true; + } + return false; +#elif __linux__ + if(socket.Socketbit != this->Socketbit) + { + return true; + } + return false; +#endif +} + +CCHostInfo CTL::Socket::GetClientHost() const { + CCHostInfo hostInfo; + if (this->IPVx == IPV4) { + char IP[INET_ADDRSTRLEN] = {0}; + inet_ntop(IPVx, &client.sin_addr, IP, INET_ADDRSTRLEN); + hostInfo.IPAddress = IP; + hostInfo.Port = ntohs(client.sin_port); + } + else if (this->IPVx == IPV6) { + char IP[INET6_ADDRSTRLEN] = {0}; + inet_ntop(IPVx, &client_6.sin6_addr, IP, INET6_ADDRSTRLEN); + hostInfo.IPAddress = IP; + hostInfo.Port = ntohs(client_6.sin6_port); + } + return hostInfo; +} + +CCHostInfo CTL::Socket::GetLocalHost() const { + CCHostInfo hostInfo; + if (this->IPVx == IPV4) { + char IP[INET_ADDRSTRLEN] = {0}; + inet_ntop(IPVx, &server.sin_addr, IP, INET_ADDRSTRLEN); + hostInfo.IPAddress = IP; + hostInfo.Port = ntohs(server.sin_port); + } + else if (this->IPVx == IPV6) { + char IP[INET6_ADDRSTRLEN] = {0}; + inet_ntop(IPVx, &server_6.sin6_addr, IP, INET6_ADDRSTRLEN); + hostInfo.IPAddress = IP; + hostInfo.Port = ntohs(server_6.sin6_port); + } + return hostInfo; +} + +void CTL::Socket::SetSocketNonBlocking() const { +#ifdef _WIN32 + u_long mode = 1; + if (ioctlsocket(this->Socketbit, FIONBIO, &mode) == SOCKET_ERROR) + { + std::cerr << "ioctlsocket failed with error: " << WSAGetLastError() << std::endl; + } +#elif __linux__ + int flags = fcntl(this->Socketbit, F_GETFL, 0); + if (flags == -1) + { + perror("fcntl(F_GETFL)"); + return; + } + flags |= O_NONBLOCK; + if (fcntl(this->Socketbit, F_SETFL, flags) == -1) + { + perror("fcntl(F_SETFL)"); + } +#endif +} + +bool CTL::Socket::isDataAvailable() const { +#ifdef _WIN32 + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(this->Socketbit, &readfds); + timeval timeout = {0, 0}; // Non-blocking check + int ret = select(0, &readfds, NULL, NULL, &timeout); + if (ret == SOCKET_ERROR) + { + //std::cerr << "select failed with error: " << WSAGetLastError() << std::endl; + return false; + } + return FD_ISSET(this->Socketbit, &readfds); +#elif __linux__ + pollfd pfd = {}; + pfd.fd = this->Socketbit; + pfd.events = POLLIN; + pfd.revents = 0; + int ret = poll(&pfd, 1, 0); // Non-blocking check + if (ret == -1) + { + perror("poll"); + return false; + } + return pfd.revents & POLLIN; +#endif +} + +bool CTL::Socket::isConnectionAlive() const { +#ifdef _WIN32 + fd_set fds; + FD_ZERO(&fds); + FD_SET(Socketbit, &fds); + timeval timeout = { 0, 0 }; // éžé˜»å¡žæ¨¡å¼ç«‹å³è¿”回 + int ret = select(Socketbit + 1, &fds, NULL, &fds, &timeout); + if (ret < 0) { + // é”™è¯¯å¤„ç† + return false; + } + else if (ret > 0) { + if (FD_ISSET(Socketbit, &fds)) { + if (FD_ISSET(Socketbit, &fds)) { + // 检查异常æ¡ä»¶ + return false; + } + } + } + return true; +#elif __linux__ + fd_set fds; + FD_ZERO(&fds); + FD_SET(Socketbit, &fds); + timeval timeout = { 0, 0 }; // éžé˜»å¡žæ¨¡å¼ç«‹å³è¿”回 + int ret = select(Socketbit + 1, &fds, NULL, &fds, &timeout); + if (ret < 0) { + // é”™è¯¯å¤„ç† + return false; + } else if (ret > 0) { + if (FD_ISSET(Socketbit, &fds)) { + if (FD_ISSET(Socketbit, &fds)) { + // 检查异常æ¡ä»¶ + return false; + } + } + } + return true; +#endif +} + +bool CTL::Socket::IsSocketWritable(const SOCKET sock) { +#ifdef _WIN32 + fd_set writefds; + FD_ZERO(&writefds); + FD_SET(sock, &writefds); + + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + int selectResult = select(0, NULL, &writefds, NULL, &timeout); + if (selectResult == -1) { + // std::cerr << "Select failed with error code: " << WSAGetLastError() << std::endl; + return false; + } else if (selectResult == 0) { + // std::cerr << "Timeout occurred. Socket not writable." << std::endl; + return false; + } + return true; +#else + fd_set writefds; + FD_ZERO(&writefds); + FD_SET(sock, &writefds); + + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + int selectResult = select(sock + 1, NULL, &writefds, NULL, &timeout); + if (selectResult == -1) { + // std::cerr << "Select failed with error code: " << errno << std::endl; + return false; + } else if (selectResult == 0) { + // std::cerr << "Timeout occurred. Socket not writable." << std::endl; + return false; + } + return true; +#endif +} + +int Socket::GetLastError() { +#ifdef _WIN32 + return WSAGetLastError(); +#else + return errno; +#endif +} + +InetAddress::InetAddress() { + Ip_x = IPV4; +} + +InetAddress::InetAddress(const IPVX ip_x,const std::string& ip) { + this->Ip_x = ip_x; + if (ip.empty()) { + const std::vector IPS = Socket::GetLocalIP(this->Ip_x); + if (!IPS.empty()) { + this->hostAddress = IPS[0]; + } + else { + this->hostAddress = "0.0.0.0"; + } + } + else { + this->hostAddress = ip; + } +} + +InetAddress InetAddress::getLocalHost(IPVX ipvx) { + const std::vector ips = Socket::GetLocalIP(ipvx, 1); + if (!ips.empty()) { + return InetAddress(ipvx,ips[0].c_str()); + } + return InetAddress(ipvx,"127.0.0.1"); +} + +std::vector InetAddress::getAllByName(const std::string &host) { + std::vector addresses; + + // 如果是IPåœ°å€æ ¼å¼ï¼Œç›´æŽ¥è¿”回 + if (host.find('.') != std::string::npos) { + addresses.push_back(host); + return addresses; + } + + // 这里应该实现DNSè§£æžï¼Œç®€åŒ–å¤„ç† + // 实际实现中需è¦è°ƒç”¨getaddrinfo等系统函数 + addresses.push_back(InetAddress("127.0.0.1", host)); + return addresses; +} + +InetAddress InetAddress::getByName(const std::string &host) { + std::vector all = getAllByName(host); + return all.empty() ? InetAddress() : all[0]; +} + +std::string InetAddress::getHostAddress() const { + return hostAddress; +} + +std::string InetAddress::getHostName() const { + if (!hostName.empty()) { + return hostName; + } + return hostAddress; // 如果没有主机å,返回IPåœ°å€ +} + +InetAddress InetAddress::getAnyAddress() { + return InetAddress("0.0.0.0"); +} + +InetAddress InetAddress::getLoopbackAddress() { + return InetAddress("127.0.0.1"); +} + +InetAddress InetAddress::getBroadcastAddress(IPVX ipvx){ + sockaddr_in serverAddr = {}; + serverAddr.sin_family = ipvx; + serverAddr.sin_addr.s_addr = INADDR_BROADCAST; + char IP[INET_ADDRSTRLEN] = {0}; + inet_ntop(ipvx, &serverAddr.sin_addr, IP, INET_ADDRSTRLEN); + return InetAddress(ipvx,IP); +} + +bool InetAddress::operator==(const InetAddress &other) const { + return this->hostAddress == other.hostAddress; +} + +bool InetAddress::operator!=(const InetAddress &other) const { + return !(*this == other); +} + +std::string InetAddress::toString() const { + return hostName.empty() ? hostAddress : (hostName + "/" + hostAddress); +} + +IPVX InetAddress::getIPx() const { + return this->Ip_x; +} + + + + + + + + diff --git a/CC_SDK_VS/Socket/CCSocket.h b/CC_SDK_VS/Socket/CCSocket.h new file mode 100644 index 0000000..3104f39 --- /dev/null +++ b/CC_SDK_VS/Socket/CCSocket.h @@ -0,0 +1,208 @@ +#ifndef CC_Socket_ +#define CC_Socket_ +#pragma once + +#include +#include "../base/CCByteArray.h" +#include "string" + +#define SockError -1 +#define CC_Sock_Close 0 + +// 定义主机信æ¯ç»“构体 +struct CCHostInfo{ + std::string IPAddress; + int Port; +}; + +// 定义套接字选项枚举 +enum CCOpt +{ + BROADCAST, + REUSEADDR, + REUSEPORT, + NOBLOCK, + LINGER_t, + SNDBUF, + RCVBUF, + TIMESTAMP, +}; + +// 定义地å€ç±»åž‹æžšä¸¾ +enum CCAddress +{ + Local, + Any +}; + + +#ifdef _WIN32 + +#define MSL_N 0 + +// Windowså¹³å°ä¸‹WSAåˆå§‹åŒ–与清ç†ç±» +class WinWSADWAInitAndClean +{ +public: + WSADATA wsd{}; + WinWSADWAInitAndClean(){ + if (WSAStartup(MAKEWORD(2, 2), &this->wsd) != 0){ + WSACleanup(); + } + } + ~WinWSADWAInitAndClean(){ + WSACleanup(); + } +}; +static WinWSADWAInitAndClean winsc; + +#elif __linux__ +#define MSL_N MSG_NOSIGNAL +#define SOCKET_ERROR (-1) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "poll.h" +typedef int SOCKET; +#endif + +// 命å空间CTL,包å«ç½‘络编程相关类和枚举 +namespace CTL { + enum IPVX + { + IPV4 = AF_INET, + IPV6 = AF_INET6 + }; + enum TORU + { + TCP = IPPROTO_TCP, + UDP = IPPROTO_UDP + }; + enum TYPE + { + STREAM = SOCK_STREAM, + DGRAM = SOCK_DGRAM + }; + + // Socket类,å°è£…äº†ç½‘ç»œç¼–ç¨‹çš„å¸¸è§æ“作 + class Socket{ + public: + SOCKET Socketbit = -1; + sockaddr_in client = {}, server = {}; + sockaddr_in6 client_6 = {}, server_6 = {}; + short IPVx = 0; + // 默认构造函数 + Socket(); + // 构造函数,åˆå§‹åŒ–Socket + Socket(SOCKET sock); + // åˆå§‹åŒ–Socket并设置属性 + bool Init(IPVX IPV4orIPV6, TORU TCPorUDP, TYPE Type = TYPE::STREAM); + // 获å–Socket奿Ÿ„ + SOCKET GetSOCKET() const; + // 设置Socket选项 + bool SetSockOpt(CCOpt opt) const; + // 设置Socket为éžé˜»å¡žæ¨¡å¼ + void SetSocketNonBlocking() const; + // 检查Socketæ˜¯å¦æœ‰å¯ç”¨æ•°æ® + bool isDataAvailable() const; + // èŽ·å–æœ¬åœ°IPåœ°å€ + static std::vector GetLocalIP(IPVX ipvx = IPVX::IPV4,int Number = 1); + // 获å–å®¢æˆ·ç«¯ä¸»æœºä¿¡æ¯ + CCHostInfo GetClientHost() const; + // èŽ·å–æœ¬åœ°ä¸»æœºä¿¡æ¯ + CCHostInfo GetLocalHost() const; + // 连接到远程主机 + bool Connect(const char* IP, unsigned short Port); + // 绑定Socket到指定地å€å’Œç«¯å£ + bool Bind(const char* IP,unsigned short Port); + // 监å¬è¿žæŽ¥è¯·æ±‚ + bool Listen(unsigned short UserNum = 10); + // 接å—连接请求 + Socket Accept() const; + // å‘逿•°æ® + bool Send(const char* str) const; + // å‘逿•°æ®ï¼Œå¸¦æ ‡å¿— + bool Send(const char *__buf, size_t __n, int __flags) const; + // å‘逿•°æ®åˆ°æŒ‡å®šåœ°å€å’Œç«¯å£ + bool SendData(const char * str,const int length,sockaddr_in addr_in) const; + // å‘逿Œ‡å®šé•¿åº¦çš„æ•°æ® + bool SendByte(const char* str,int len) const; + // å‘逿Œ‡å®šé•¿åº¦çš„æ•°æ® + bool SendByte(const char* str,int len,int* ret) const; + // UDPå‘逿•°æ® + bool UDPSend(const char* str,const char* IP,int Port) const; + // UDPå‘逿Œ‡å®šé•¿åº¦çš„æ•°æ® + bool UDPSendByte(const char* str, ByteHander len, const char* IP, int Port) const; + // UDPå‘逿Œ‡å®šé•¿åº¦çš„æ•°æ® + bool UDPSendByte(void* str, ByteHander len, const char* IP, int Port) const; + // æŽ¥æ”¶æ•°æ® + ByteHander RecvData(char* buffer,ByteHander lens) const; + // UDPæŽ¥æ”¶æ•°æ® + ByteHander UDPRecvData(char* buffer,ByteHander lens,CCHostInfo* info) const; + // 关闭Socket + void Close(); + // èŽ·å–æ•°æ®å¤´éƒ¨ + static bool GetDateHead(char* data, ByteHander* size); + // 获å–字符串头部 + static bool GetStrHead(char* data,ByteHander size); + // é‡è½½ç­‰å·è¿ç®—符,比较Socket对象是å¦ç›¸ç­‰ + bool operator == (Socket socket) const; + // é‡è½½ä¸ç­‰å·è¿ç®—符,比较Socket对象是å¦ä¸ç­‰ + bool operator != (Socket socket) const; + // æ£€æŸ¥è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆ + bool isConnectionAlive() const; + // 检查Socket是å¦å¯å†™ + static bool IsSocketWritable(SOCKET sock); + static int GetLastError(); + private: + int sock; + bool Stop; + int opt; + }; + class InetAddress { + std::string hostAddress; + std::string hostName; + IPVX Ip_x; + public: + // 默认构造函数 + InetAddress(); + // æ ¹æ®IPåœ°å€æž„造 + InetAddress(const std::string& ip) : hostAddress(ip) {} + InetAddress(IPVX ip_x,const std::string& ip= ""); + // æ ¹æ®IP地å€å’Œä¸»æœºå构造 + InetAddress(const std::string& ip, const std::string& hostname) + : hostAddress(ip), hostName(hostname) {} + // èŽ·å–æœ¬åœ°ä¸»æœºInetAddress对象 + static InetAddress getLocalHost(IPVX ipvx = IPVX::IPV4); + // æ ¹æ®ä¸»æœºå获å–InetAddress对象 + static std::vector getAllByName(const std::string& host); + // æ ¹æ®IP地å€èŽ·å–InetAddress对象 + static InetAddress getByName(const std::string& host); + // 获å–IP地å€å­—符串 + std::string getHostAddress() const; + // 获å–主机å + std::string getHostName() const; + // 获å–ä»»æ„åœ°å€ (相当于Java中的InetAddress.getByName("0.0.0.0")) + static InetAddress getAnyAddress(); + // 获å–å›žçŽ¯åœ°å€ (相当于Java中的InetAddress.getByName("localhost")) + static InetAddress getLoopbackAddress(); + // 获å–å¹¿æ’­åœ°å€ + static InetAddress getBroadcastAddress(IPVX ipvx = IPVX::IPV4); + // é‡è½½ç›¸ç­‰è¿ç®—符 + bool operator==(const InetAddress& other) const; + // é‡è½½ä¸ç­‰è¿ç®—符 + bool operator!=(const InetAddress& other) const; + // 转æ¢ä¸ºå­—符串 + std::string toString() const; + IPVX getIPx() const; + }; +} + + +#endif diff --git a/CC_SDK_VS/TL/Array_CTL.h b/CC_SDK_VS/TL/Array_CTL.h new file mode 100644 index 0000000..11838d2 --- /dev/null +++ b/CC_SDK_VS/TL/Array_CTL.h @@ -0,0 +1,118 @@ +#ifndef CTL_ARRAY_CTL_H +#define CTL_ARRAY_CTL_H + + + +namespace CTL { + template + class Array_CTL { + public: + private: + struct BinaryTree { + size_t Key = 0; + V* value = nullptr; + BinaryTree* left = nullptr; + BinaryTree* right = nullptr; + }; + BinaryTree* root = nullptr; + size_t _size_m = 0; + public: + Array_CTL() { + delete root; + root = new BinaryTree(); + } + ~Array_CTL() { + clear(this->root); + } + void add(const V value) { + insert(_size_m, value); + } + void clear() { + clear(this->root); + } + V get(const size_t index) { + return *find(index,this->root); + } + V* getPtr(const size_t index) { + return find(index,this->root); + } + private: + void clear(BinaryTree* node) { + if (node) { + clear(node->left); + clear(node->right); + delete node->value; + node->value = nullptr; + delete node; + node = nullptr; + _size_m--; + } + } + V* find(int key, const BinaryTree* node) { + V* value = nullptr; + if (node) { + if (node->Key == key) { + return node->value; + } + else if (node->Key < key) { + if (node->right) { + return find(key,node->right); + } + } + else if (node->Key > key) { + if (node->left) { + return find(key,node->left); + } + } + } + return value; + } + void insert(size_t key,V value) { + V* newValue = new V(value); + + if (!this->root) { + this->root = new BinaryTree(); + this->root->Key = key; + this->root->value = newValue; + _size_m++; + return; + } + + BinaryTree* current = this->root; + while (current) { + if (key == current->Key) { + if (current->value) { + delete current->value; + } + else { + _size_m++; + } + current->value = newValue; + return; + } + else if (key < current->Key) { + if (!current->left) { + current->left = new BinaryTree(); + current->left->Key = key; + current->left->value = newValue; + _size_m++; + return; + } + current = current->left; + } + else { + if (!current->right) { + current->right = new BinaryTree(); + current->right->Key = key; + current->right->value = newValue; + _size_m++; + return; + } + current = current->right; + } + } + } + }; +} + +#endif diff --git a/CC_SDK_VS/TL/AutoDestruct.h b/CC_SDK_VS/TL/AutoDestruct.h new file mode 100644 index 0000000..d3c0cea --- /dev/null +++ b/CC_SDK_VS/TL/AutoDestruct.h @@ -0,0 +1,65 @@ +#ifndef SDK_TL_AUTODESTRUCT_H +#define SDK_TL_AUTODESTRUCT_H + +#include "iostream" + +namespace CTL{ + template + class AutoDestruct{ + T* m_ptr; + bool m_is_owner; + public: + //-------------------------------------------------------------------------------------------------------------- + AutoDestruct(T* ptr) { + this->m_ptr = ptr; + m_is_owner = true; + } + AutoDestruct(AutoDestruct&& other) { + this->m_ptr = other.m_ptr; + other.m_ptr = NULL; + } + ~AutoDestruct(){ + if (m_ptr && m_is_owner) { + delete m_ptr; + } + m_ptr = NULL; + } + //-------------------------------------------------------------------------------------------------------------- + T* Get(){ + return m_ptr; + } + const T* Get() const{ + return m_ptr; + } + T* get(){ + return m_ptr; + } + const T* get() const{ + return m_ptr; + } + operator bool() const { + return m_ptr != NULL; + } + T& operator*() const { + return *m_ptr; // å‡è®¾ ptr 是内部 Term* + } + T* operator->() const { + return m_ptr; // å‡è®¾ ptr 是内部 Term* + } + AutoDestruct& operator=(T* ptr){ + delete m_ptr; + m_ptr = ptr; + return *this; + } + void reset(T* ptr = NULL){ + delete m_ptr; + m_ptr = ptr; + } + void release() { + m_is_owner = false; + } + //-------------------------------------------------------------------------------------------------------------- + }; +} + +#endif diff --git a/CC_SDK_VS/TL/List.h b/CC_SDK_VS/TL/List.h new file mode 100644 index 0000000..8034a94 --- /dev/null +++ b/CC_SDK_VS/TL/List.h @@ -0,0 +1,202 @@ +#ifndef SDK_TL_LIST_H +#define SDK_TL_LIST_H + +#include "list" +#include "mutex" +#include "iostream" +#include "vector" + +namespace CTL{ + template + class List{ + private: + std::mutex _mutex; + std::list _list; + public: + //-------------------------------------------------------------------------------------------------------------- + List() = default; + explicit List(const std::list list){ + _list = list; + } + explicit List(const std::vector list){ + for (int i = 0; i < list.size(); ++i) { + _list.push_back(list[i]); + } + } + List(const List& list) { + auto L = list._list; + for (auto O : L) { + _list.push_back(O); + } + } + List(const std::initializer_list& list) { + for (auto item : list) { + _list.push_back(item); + } + } + ~List() = default; + //-------------------------------------------------------------------------------------------------------------- + friend std::ostream& operator<<(std::ostream& os, const List& list) { + os << "["; + const auto& items = list._list; + if (!items.empty()) { + auto it = items.begin(); + os << *it; + ++it; + for (; it != items.end(); ++it) { + os << "," << *it; + } + } + os << "]"; + return os; + } + //-------------------------------------------------------------------------------------------------------------- + void Add(const T &item){ + _mutex.lock(); + _list.push_back(item); + _mutex.unlock(); + } + bool Set(const int index, const T &item){ + _mutex.lock(); + if (index >= 0 && index < _list.size()) { + auto it = _list.begin(); + std::advance(it, index); // 将迭代器移动到指定索引 + *it = item; // 修改该ä½ç½®çš„值 + _mutex.unlock(); + return true; + } + else { + _mutex.unlock(); + return false; + } + } + T* Get(int index){ + _mutex.lock(); // 加é”,ä¿è¯çº¿ç¨‹å®‰å…¨ + if (index >= 0 && index < _list.size()) { // 检查索引是å¦åˆæ³• + auto it = _list.begin(); + std::advance(it, index); // 将迭代器移动到指定索引 + _mutex.unlock(); // è§£é” + return &(*it); // 返回元素的指针(原代ç è¿”回 it 是错误的,应返回指å‘对象的指针) + } + else { + _mutex.unlock(); // è§£é” + return nullptr; // 索引越界返回空指针 + } + } + bool Remove(int index){ + _mutex.lock(); + if (index >= 0 && index < _list.size()) { + auto it = _list.begin(); + std::advance(it, index); + _list.erase(it); + _mutex.unlock(); + return true; + } + else { + _mutex.unlock(); + return false; + } + } + void RemoveAll(const T& item){ + _mutex.lock(); + _list.remove(item); + _mutex.unlock(); + } + void Clear(){ + _mutex.lock(); + _list.clear(); + _mutex.unlock(); + } + int Size(){ + _mutex.lock(); + int size = _list.size(); + _mutex.unlock(); + return size; + } + bool IsEmpty(){ + _mutex.lock(); + bool isEmpty = _list.empty(); + _mutex.unlock(); + return isEmpty; + } + bool Insert(const int index, const T &item){ + _mutex.lock(); + if (index >= 0 && index <= _list.size()) { + auto it = _list.begin(); + std::advance(it, index); + _list.insert(it, item); + _mutex.unlock(); + return true; + } + else { + _mutex.unlock(); + return false; + } + } + void Sort(){ + _mutex.lock(); + _list.sort(); + _mutex.unlock(); + } + void Reverse(){ + _mutex.lock(); + _list.reverse(); + _mutex.unlock(); + } + int find(const T& value) { + const int count = _list.size(); + for (int i = 0; i < count; ++i) { + if(Get(i) == &value){ + return i; + } + } + return -1; // 未找到 + } + bool IsContains(const T& item){ + _mutex.lock(); + bool isContains = find(item) != -1; + _mutex.unlock(); + return isContains; + } + std::list ToList(){ + _mutex.lock(); + std::list list = _list; + _mutex.unlock(); + return list; + } + std::vector ToVector(){ + _mutex.lock(); + std::vector vector; + for (auto& item : _list) { + vector.push_back(item); + } + _mutex.unlock(); + return vector; + } + typename std::list::iterator begin() { + return _list.begin(); + } + typename std::list::iterator end() { + return _list.end(); + } + List operator=(const List& list){ + _mutex.lock(); + _list = list._list; + _mutex.unlock(); + return list; + } + List operator=(const std::list& list){ + _mutex.lock(); + _list = list; + _mutex.unlock(); + return *this; + } + //-------------------------------------------------------------------------------------------------------------- + private: + //-------------------------------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------------------------------- + }; +} + + +#endif diff --git a/CC_SDK_VS/TL/Map.h b/CC_SDK_VS/TL/Map.h new file mode 100644 index 0000000..ea03f19 --- /dev/null +++ b/CC_SDK_VS/TL/Map.h @@ -0,0 +1,209 @@ +#ifndef SDK_TL_MAP_H +#define SDK_TL_MAP_H + +#include "iostream" +#include "vector" +#include "list" +#include "map" +#include "mutex" +#include "string" +#include "shared_mutex" + +namespace CTL{ + template + class Map{ + private: + //-------------------------------------------------------------------------------------------------------------- + mutable std::shared_mutex _mutex; + std::map _map; + //-------------------------------------------------------------------------------------------------------------- + public: + //-------------------------------------------------------------------------------------------------------------- + friend std::ostream& operator<<(std::ostream& os,Map& map) { + os << "[\n"; + auto items = map.ToStdMap(); + auto it = items.begin(); + while (it != items.end()) { + os << " {\n " << it->first << ": " << it->second << "\n }"; + ++it; + if (it != items.end()) { + os << ",\n"; + } + } + os << "\n]"; + return os; + } + friend std::ostream& operator<<(std::ostream& os,const Map& map) { + os << "[\n"; + auto items = map.ToStdMap(); + auto it = items.begin(); + while (it != items.end()) { + os << " {\n " << it->first << ": " << it->second << "\n }"; + ++it; + if (it != items.end()) { + os << ",\n"; + } + } + os << "\n]"; + return os; + } + //-------------------------------------------------------------------------------------------------------------- + Map() = default; + explicit Map(const std::map& map){ + std::lock_guard lock(_mutex); + _map = map; + } + Map(const Map& map){ + std::lock_guard lock(_mutex); + this->_map = map._map; + } + Map(const std::initializer_list>& list){ + std::lock_guard lock(_mutex); + for (const auto& item : list) { + _map.insert(item); + } + } + ~Map() { + Clear(); + } + //-------------------------------------------------------------------------------------------------------------- + void Put(K key, V value){ + std::lock_guard lock(_mutex); + _map.insert(std::make_pair(key, value)); + } + void put(K key, V value){ + Put(key,value); + } + void Revise(K key, V value){ + std::lock_guard lock(_mutex); + _map[key] = value; + } + void revise(K key, V value){ + std::lock_guard lock(_mutex); + _map[key] = value; + } + void Remove(K key){ + std::lock_guard lock(_mutex); + _map.erase(key); + } + void remove(K key){ + std::lock_guard lock(_mutex); + _map.erase(key); + } + void Clear(){ + std::lock_guard lock(_mutex); + std::map().swap(this->_map); + } + void clear(){ + std::lock_guard lock(_mutex); + std::map().swap(this->_map); + } + static void swap(Map* map) { + std::map().swap(map->_map); + } + V* Get(const K& key){ + std::shared_lock lock(_mutex); + const bool F = _map.find(key) != _map.end(); + if (!F) { + return nullptr; + } + return &_map[key]; + } + V* get(const K& key){ + return Get(key); + } + V at(const K& key) const{ + std::shared_lock lock(_mutex); + return _map.at(key); + } + V* operator[](const K& key){ + std::shared_lock lock(_mutex); + const bool F = _map.find(key) != _map.end(); + if (!F) { + return nullptr; + } + return &_map[key]; + } + int Size(){ + std::shared_lock lock(_mutex); + return _map.size(); + } + int size(){ + std::shared_lock lock(_mutex); + return _map.size(); + } + bool IsContains(const K& key){ + std::shared_lock lock(_mutex); + return _map.find(key) != _map.end(); + } + bool IsEmpty(){ + std::shared_lock lock(_mutex); + return _map.empty(); + } + bool IsFull(){ + std::shared_lock lock(_mutex); + return _map.size() == _map.max_size(); + } + std::list Keys(){ + std::shared_lock lock(_mutex); + std::list keys; + for(auto& item : _map){ + keys.push_back(item.first); + } + return keys; + } + std::list keys(){ + return Keys(); + } + std::vector Values(){ + std::shared_lock lock(_mutex); + std::vector values; + for(auto& item : _map){ + values.push_back(item.second); + } + return values; + } + std::vector values(){ + return Values(); + } + std::map ToStdMap(){ + return _map; + } + std::map ToStdMap() const { // å®žçŽ°å¤„åŒæ ·æ·»åŠ  const + return _map; // å‡è®¾å†…部存储为 _map + } + void SetStdMap(const Map& map) { + std::lock_guard lock(_mutex); + _map = map._map; + } + void SetStdMap(const std::map& map) { + std::lock_guard lock(_mutex); + _map = map; + } + typename std::map::iterator begin() { + return _map.begin(); + } + typename std::map::iterator end() { + return _map.end(); + } + Map operator=(const Map& map) { + std::lock_guard lock(_mutex); + _map = map._map; + return map; + } + Map operator=(const std::map& map) { + std::lock_guard lock(_mutex); + _map = map; + return this; + } + //-------------------------------------------------------------------------------------------------------------- + private: + }; + template + class MapPtr:public Map { + public: + + }; +} + +#endif diff --git a/CC_SDK_VS/TL/Map_CTL.h b/CC_SDK_VS/TL/Map_CTL.h new file mode 100644 index 0000000..d1a8ac2 --- /dev/null +++ b/CC_SDK_VS/TL/Map_CTL.h @@ -0,0 +1,409 @@ +#ifndef MAP_CTL_H +#define MAP_CTL_H + +#include +#include +#include + +namespace CTL { + enum COLOR{ + BLACK_t, + RED_t + }; + template + struct RBTreeNode{ + RBTreeNode* _parent; //父节点 + RBTreeNode* _left; //å·¦å­©å­ + RBTreeNode* _right; //å³å­©å­ + V _val; + COLOR _color; //颜色 + explicit RBTreeNode(const V& val = V()) + :_parent(nullptr) + , _left(nullptr) + , _right(nullptr) + , _val(val) + , _color(RED_t) { + + } + }; + template + class RBTree{ + public: + typedef RBTreeNode Node; + RBTree():_header(new Node){ + _header->_left = _header->_right = _header; + } + ~RBTree() { + clear(); + delete _header; + _header = nullptr; + } + bool insert(const V& val){ + if (_header->_parent == nullptr){ + Node* root = new Node(val); + _header->_parent = root; + root->_parent = _header; + _header->_left = _header->_right = root; + //根节点为黑色 + root->_color = BLACK_t; + return true; + } + + Node* cur = _header->_parent; + Node* parent = nullptr; + + KeyOfValue kov; + //1.å¯»æ‰¾åˆ°è¦æ’入的结点的ä½ç½® + while (cur){ + parent = cur; + if (kov(cur->_val) == kov(val)) { + return false; + } + else if (kov(cur->_val) > kov(val)) { + cur = cur->_left; + } + else { + cur = cur->_right; + } + } + //2.创建节点 + cur = new Node(val); + if (kov(parent->_val) > kov(cur->_val)) { + parent->_left = cur; + } + else { + parent->_right = cur; + } + cur->_parent = parent; + + //3.颜色的修改或者结构的调整 + while (cur != _header->_parent && cur->_parent->_color == RED_t){ //ä¸ä¸ºæ ¹ä¸”存在连续红色,则需è¦è°ƒæ•´ + parent = cur->_parent; + Node* gfather = parent->_parent; + + if (gfather->_left == parent){ + Node* uncle = gfather->_right; + //情况1.uncle存在且为红 + if (uncle && uncle->_color == RED_t){ + parent->_color = uncle->_color = BLACK_t; + gfather->_color = RED_t; + //å‘上追溯 + cur = gfather; + } + else{ + if (parent->_right == cur){ //情况3 + RotateL(parent); + swap(cur, parent); + } + //情况2.uncleä¸å­˜åœ¨æˆ–者uncle为黑 + RotateR(gfather); + parent->_color = BLACK_t; + gfather->_color = RED_t; + break; + } + } + else{ + Node* uncle = gfather->_left; + if (uncle && uncle->_color == RED_t){ + parent->_color = uncle->_color = BLACK_t; + gfather->_color = RED_t; + //å‘上追溯 + cur = gfather; + } + else{ + if (parent->_left == cur){ + RotateR(parent); + swap(cur, parent); + } + + RotateL(gfather); + parent->_color = BLACK_t; + gfather->_color = RED_t; + break; + } + } + } + + //根节点为黑色 + _header->_parent->_color = BLACK_t; + //æ›´æ–°å¤´ç»“ç‚¹çš„å·¦å³æŒ‡å‘ + _header->_left = leftMost(); + _header->_right = rightMost(); + return true; + } + void RotateL(Node* parent){ + Node* subR = parent->_right; + Node* subRL = subR->_left; + + parent->_right = subRL; + if (subRL) { + subRL->_parent = parent; + } + if (parent == _header->_parent){ + _header->_parent = subR; + subR->_parent = _header; + } + else{ + Node* gfather = parent->_parent; + if (gfather->_left == parent) { + gfather->_left = subR; + } + else { + gfather->_right = subR; + } + subR->_parent = gfather; + } + subR->_left = parent; + parent->_parent = subR; + } + void RotateR(Node* parent){ + Node* subL = parent->_left; + Node* subLR = subL->_right; + + parent->_left = subLR; + if (subLR) { + subLR->_parent = parent; + } + + if (parent == _header->_parent){ + _header->_parent = subL; + subL->_parent = _header; + } + else{ + Node* gfather = parent->_parent; + if (gfather->_left == parent) { + gfather->_left = subL; + } + else { + gfather->_right = subL; + } + subL->_parent = gfather; + } + subL->_right = parent; + parent->_parent = subL; + } + Node* leftMost() const { + Node* cur = _header->_parent; + while (cur && cur->_left){ + cur = cur->_left; + } + return cur; + } + Node* rightMost() const { + Node* cur = _header->_parent; + while (cur && cur->_right){ + cur = cur->_right; + } + return cur; + } + Node* leftMostPublic() const { + Node* node = leftMost(); + if (node == _header) { + return nullptr; + } + return node; + } + Node* getRoot() const { + return _header->_parent; + } + Node* findNode(const K& key) { + Node* cur = getRoot(); + KeyOfValue kov; + while (cur) { + if (kov(cur->_val) == key) { + return cur; + } + else if (kov(cur->_val) > key) { + cur = cur->_left; + } + else { + cur = cur->_right; + } + } + return nullptr; + } + Node* getHeader() const { + return _header; + } + bool erase(const K& key) { + Node* node = findNode(key); + if (!node) return false; + + // 实际删除节点的逻辑 + deleteNode(node); + return true; + } + void clear() { + destroy(_header->_parent); + _header->_parent = nullptr; + _header->_left = _header->_right = _header; + } + private: + void destroy(Node* node) { + if (!node || node == _header) return; + std::stack nodes_to_delete; + nodes_to_delete.push(node); + while (!nodes_to_delete.empty()) { + Node* current = nodes_to_delete.top(); + nodes_to_delete.pop(); + if (current->_left && current->_left != _header && current->_left != nullptr) { + nodes_to_delete.push(current->_left); + } + if (current->_right && current->_right != _header && current->_right != nullptr) { + nodes_to_delete.push(current->_right); + } + delete current; + current = nullptr; + } + } + void destroy_t(Node* node) { + if (node && node != _header) { + destroy(node->_left); + destroy(node->_right); + delete node; + node = nullptr; + } + } + void deleteNode(Node* node) { + // ç®€åŒ–çš„åˆ é™¤å®žçŽ°ï¼ˆå®žé™…çº¢é»‘æ ‘åˆ é™¤æ›´å¤æ‚) + if (node->_left && node->_right) { + // 找到中åºåŽç»§ + Node* successor = node->_right; + while (successor->_left) { + successor = successor->_left; + } + + // 交æ¢å€¼ + std::swap(node->_val, successor->_val); + + // 删除åŽç»§èŠ‚ç‚¹ + deleteNode(successor); + return; + } + + // èŠ‚ç‚¹æœ€å¤šåªæœ‰ä¸€ä¸ªå­èŠ‚ç‚¹ + Node* child = node->_left ? node->_left : node->_right; + if (!node->_parent) { + // 删除根节点 + _header->_parent = child; + } else if (node == node->_parent->_left) { + node->_parent->_left = child; + } else { + node->_parent->_right = child; + } + + if (child) { + child->_parent = node->_parent; + } + + delete node; + + // 更新边界节点 + if (_header->_parent) { + _header->_left = leftMost(); + _header->_right = rightMost(); + } else { + _header->_left = _header->_right = _header; + } + } + public: + private: + Node* _header = nullptr; + }; + template + class Map_CTL { + struct MapKeyOfValue{ + const K& operator()(const std::pair& val){ + return val.first; + } + }; + typedef RBTree, MapKeyOfValue> rbt; + rbt _rbt; + public: + class iterator { + typename rbt::Node* _node; + const Map_CTL* _map; + const rbt* _tree; + public: + iterator(typename rbt::Node* node, const rbt* tree) + : _node(node), _map(nullptr), _tree(tree) { + } + iterator& operator++() { + if (_node) { + // 如果有å³å­æ ‘,找到å³å­æ ‘的最左节点 + if (_node->_right) { + _node = _node->_right; + while (_node->_left) { + _node = _node->_left; + } + } else { + // å¦åˆ™å‘上找到第一个父节点,当å‰èŠ‚ç‚¹åœ¨å…¶å·¦å­æ ‘中 + typename rbt::Node* parent = _node->_parent; + while (parent && _node == parent->_right) { + _node = parent; + parent = parent->_parent; + } + // 检查是å¦åˆ°è¾¾äº† header(å³é历完æˆï¼‰ + if (parent == _tree->getHeader()) { + _node = nullptr; + } else { + _node = parent; + } + } + } + return *this; + } + iterator operator++(int) { + iterator temp = *this; + ++(*this); + return temp; + } + std::pair& operator*() const { + return _node->_val; + } + std::pair* operator->() const { + return &(_node->_val); + } + bool operator==(const iterator& other) const { + return _node == other._node && _map == other._map; + } + bool operator!=(const iterator& other) const { + return !(*this == other); + } + }; + friend class iterator; + private: + bool insert(const std::pair& kv){ + return _rbt.insert(kv); + } + public: + Map_CTL() = default; + ~Map_CTL() { + clear(); + } + void put(const K& key, const V& value) { + insert(std::pair(key,value)); + } + V* get(const K& key) { + typename rbt::Node* node = _rbt.findNode(key); + if (node) { + return &(node->_val.second); + } + return nullptr; + } + void remove(const K& key) { + _rbt.erase(key); + } + void clear() { + _rbt.clear(); + } + iterator begin() { + return iterator(_rbt.leftMostPublic(), &_rbt); + } + iterator end() { + return iterator(nullptr, &_rbt); + } + }; +} + +#endif diff --git a/CC_SDK_VS/TL/Queue.h b/CC_SDK_VS/TL/Queue.h new file mode 100644 index 0000000..e2973b2 --- /dev/null +++ b/CC_SDK_VS/TL/Queue.h @@ -0,0 +1,69 @@ +#ifndef SDK_TL_QUEUE_H +#define SDK_TL_QUEUE_H + +#include "mutex" +#include "AutoDestruct.h" +#include "deque" + +namespace CTL{ + template + class Queue{ + private: + //-------------------------------------------------------------------------------------------------------------- + std::mutex _mutex; + std::deque _deque; + //-------------------------------------------------------------------------------------------------------------- + public: + //-------------------------------------------------------------------------------------------------------------- + Queue() = default; + ~Queue() = default; + //-------------------------------------------------------------------------------------------------------------- + void Add(const T& data){ + _mutex.lock(); + _deque.push_back(std::move(data)); + _mutex.unlock(); + } + void AddFirst(const T& data){ + _mutex.lock(); + _deque.push_front(std::move(data)); + _mutex.unlock(); + } + AutoDestruct Poll(){ + _mutex.lock(); + if(_deque.empty()){ + _mutex.unlock(); + return nullptr; + } + T* data = new T(_deque.front()); + _deque.pop_front(); + _mutex.unlock(); + return data; + } + AutoDestruct PollBack(){ + _mutex.lock(); + if(_deque.empty()){ + _mutex.unlock(); + return nullptr; + } + T* data = new T(_deque.back()); + _deque.pop_back(); + _mutex.unlock(); + return data; + } + bool IsEmpty(){ + _mutex.lock(); + bool empty = _deque.empty(); + _mutex.unlock(); + return empty; + } + int Size(){ + _mutex.lock(); + int size = _deque.size(); + _mutex.unlock(); + return size; + } + //-------------------------------------------------------------------------------------------------------------- + }; +} + +#endif diff --git a/WebSocket/CCWebSocket.cpp b/CC_SDK_VS/WebSocket/CCWebSocket.cpp similarity index 100% rename from WebSocket/CCWebSocket.cpp rename to CC_SDK_VS/WebSocket/CCWebSocket.cpp diff --git a/WebSocket/CCWebSocket.h b/CC_SDK_VS/WebSocket/CCWebSocket.h similarity index 74% rename from WebSocket/CCWebSocket.h rename to CC_SDK_VS/WebSocket/CCWebSocket.h index ef0edc4..6c47114 100644 --- a/WebSocket/CCWebSocket.h +++ b/CC_SDK_VS/WebSocket/CCWebSocket.h @@ -1,6 +1,8 @@ #ifndef CC_WEBSOCKET_H #define CC_WEBSOCKET_H +#include "../CCMutex.h" +#include "../CCThreadPool.h" namespace CTL{ class WebSocket { diff --git a/WebSocket/base64.cpp b/CC_SDK_VS/WebSocket/base64.cpp similarity index 100% rename from WebSocket/base64.cpp rename to CC_SDK_VS/WebSocket/base64.cpp diff --git a/WebSocket/base64.h b/CC_SDK_VS/WebSocket/base64.h similarity index 100% rename from WebSocket/base64.h rename to CC_SDK_VS/WebSocket/base64.h diff --git a/WebSocket/sha1.h b/CC_SDK_VS/WebSocket/sha1.h similarity index 100% rename from WebSocket/sha1.h rename to CC_SDK_VS/WebSocket/sha1.h diff --git a/WebSocket/sha1_portable.cpp b/CC_SDK_VS/WebSocket/sha1_portable.cpp similarity index 100% rename from WebSocket/sha1_portable.cpp rename to CC_SDK_VS/WebSocket/sha1_portable.cpp diff --git a/WebSocket/string_helper.cpp b/CC_SDK_VS/WebSocket/string_helper.cpp similarity index 100% rename from WebSocket/string_helper.cpp rename to CC_SDK_VS/WebSocket/string_helper.cpp diff --git a/WebSocket/string_helper.h b/CC_SDK_VS/WebSocket/string_helper.h similarity index 100% rename from WebSocket/string_helper.h rename to CC_SDK_VS/WebSocket/string_helper.h diff --git a/WebSocket/string_helper.inl b/CC_SDK_VS/WebSocket/string_helper.inl similarity index 100% rename from WebSocket/string_helper.inl rename to CC_SDK_VS/WebSocket/string_helper.inl diff --git a/WebSocket/ws_endpoint.cpp b/CC_SDK_VS/WebSocket/ws_endpoint.cpp similarity index 100% rename from WebSocket/ws_endpoint.cpp rename to CC_SDK_VS/WebSocket/ws_endpoint.cpp diff --git a/WebSocket/ws_endpoint.h b/CC_SDK_VS/WebSocket/ws_endpoint.h similarity index 100% rename from WebSocket/ws_endpoint.h rename to CC_SDK_VS/WebSocket/ws_endpoint.h diff --git a/WebSocket/ws_packet.cpp b/CC_SDK_VS/WebSocket/ws_packet.cpp similarity index 100% rename from WebSocket/ws_packet.cpp rename to CC_SDK_VS/WebSocket/ws_packet.cpp diff --git a/WebSocket/ws_packet.h b/CC_SDK_VS/WebSocket/ws_packet.h similarity index 100% rename from WebSocket/ws_packet.h rename to CC_SDK_VS/WebSocket/ws_packet.h diff --git a/CC_SDK_VS/base/CCByte.h b/CC_SDK_VS/base/CCByte.h new file mode 100644 index 0000000..ad10d2c --- /dev/null +++ b/CC_SDK_VS/base/CCByte.h @@ -0,0 +1,188 @@ +#ifndef CC_BYTE_H +#define CC_BYTE_H + +#include +#include +#include + +#include "iostream" + +namespace CTL { + class Byte { + uint8_t value; // 存储å•ä¸ªå­—èŠ‚çš„æ•°æ® + public: + // 构造函数 + Byte(const uint8_t& val = 0) : value(val) {} + Byte(const char& c) { + value = c; + } + Byte(const int& val) { + value = val; + } + Byte(const size_t& val) { + value = val; + } + // 获å–当å‰å­—节的值 + [[nodiscard]] uint8_t get() const { + return value; + } + // 设置当å‰å­—节的值 + void set(const uint8_t val) { + value = val; + } + // 按ä½ä¸Žæ“作 + Byte operator&(const Byte& other) const { + return Byte(value & other.value); + } + // æŒ‰ä½æˆ–æ“作 + Byte operator|(const Byte& other) const { + return Byte(value | other.value); + } + // 按ä½å¼‚或æ“作 + Byte operator^(const Byte& other) const { + return Byte(value ^ other.value); + } + // 按ä½å–åæ“ä½œ + Byte operator~() const { + return Byte(~value); + } + // 左移æ“作 + Byte operator<<(int n) const { + return Byte(value << n); + } + // å³ç§»æ“作 + Byte operator>>(int n) const { + return Byte(value >> n); + } + bool operator==(const Byte& other) const { + return value == other.value; + } + bool operator!=(const Byte& other) const { + return value != other.value; + } + bool operator<(const Byte& other) const { + return value < other.value; + } + bool operator>(const Byte& other) const { + return value > other.value; + } + bool operator<=(const Byte& other) const { + return value <= other.value; + } + bool operator>=(const Byte& other) const { + return value >= other.value; + } + bool operator==(const int& other) const { + return value == other; + } + bool operator!=(const int& other) const { + return value != other; + } + bool operator<(const int& other) const { + return value < other; + } + bool operator>(const int& other) const { + return value > other; + } + bool operator<=(const int& other) const { + return value <= other; + } + bool operator>=(const int& other) const { + return value >= other; + } + Byte& operator=(const Byte& other) = default; + Byte& operator=(uint8_t val) { + value = val; + return *this; + } + Byte operator++() { + ++value; + return *this; + } + Byte operator++(int) { + Byte temp = *this; + ++value; + return temp; + } + Byte operator--() { + --value; + return *this; + } + Byte operator--(int) { + Byte temp = *this; + --value; + return temp; + } + Byte operator+=(const Byte& other) { + value += other.value; + return *this; + } + Byte operator-=(const Byte& other) { + value -= other.value; + return *this; + } + Byte operator*=(const Byte& other) { + value *= other.value; + return *this; + } + Byte operator/=(const Byte& other) { + value /= other.value; + return *this; + } + Byte operator%=(const Byte& other) { + value %= other.value; + return *this; + } + Byte operator<<=(int n) { + value <<= n; + return *this; + } + Byte operator>>=(int n) { + value >>= n; + return *this; + } + operator uint8_t() const { + return value; + } + operator uint8_t() { + return value; + } + operator char() const { + return value; + } + operator char() { + return value; + } + // æä¾›æ˜¾å¼çš„è½¬æ¢æ“作符 + operator int() const { + return static_cast(value); + } + operator int() { + return static_cast(value); + } + // 输出字节的二进制表示 + friend std::ostream& operator<<(std::ostream& os, const Byte& byte) { + for (int i = 7; i >= 0; --i) { + os << ((byte.value >> i) & 1); + } + return os; + } + friend std::istream& operator>>(std::istream& is, Byte& byte) { + uint8_t val; + is >> val; + byte.value = val; + return is; + } + static Byte* fromCString(const char* cstr) { + size_t length = strlen(cstr); + auto* bytes = new Byte[length + 1]; + for (size_t i = 0; i < length; ++i) { + bytes[i] = cstr[i]; + } + bytes[length] = '\0'; + return bytes; + } + }; +} + +#endif diff --git a/CC_SDK_VS/base/CCByteArray.cpp b/CC_SDK_VS/base/CCByteArray.cpp new file mode 100644 index 0000000..8c10b39 --- /dev/null +++ b/CC_SDK_VS/base/CCByteArray.cpp @@ -0,0 +1,454 @@ +#include "CCByteArray.h" + +#include +#include + +#include "vector" +#include "list" + +using namespace CTL; + +static const char base64_chars[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +"abcdefghijklmnopqrstuvwxyz" +"0123456789+/"; + +static const unsigned char base64_decode_table[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, + 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +ByteArray::ByteArray(const std::string &str) { + bytes.assign(str.begin(), str.end()); +} + +ByteArray::ByteArray(const void *str, const size_t size) { + this->Conversion<>(str,size); +} + +ByteArray::ByteArray(const char *str) { + bytes.assign(str, str + strlen(str)); +} + +ByteArray::ByteArray(const ByteArray &other) { + bytes.assign(other.bytes.begin(), other.bytes.end()); +} + +ByteArray::ByteArray(const std::vector &bytes) { + this->bytes.assign(bytes.begin(), bytes.end()); +} + +ByteArray::ByteArray(const std::list &bytes) { + this->bytes.assign(bytes.begin(), bytes.end()); +} + +ByteArray::ByteArray(const Byte *bytes) { + this->bytes.assign(bytes, bytes + strlen(reinterpret_cast(bytes))); +} + +ByteArray::ByteArray(const ByteHander size) { + bytes.resize(size); +} + +void ByteArray::add(const Byte byte) { + bytes.push_back(byte); +} + +Byte ByteArray::get(const int index) const { + if (index < 0 || index >= bytes.size()) { + throw std::out_of_range("Index out of range"); + } + return bytes[index]; +} + +void ByteArray::set(const int index, const Byte byte) { + if (index < 0 || index >= bytes.size()) { + throw std::out_of_range("Index out of range"); + } + bytes[index] = byte; +} + +void ByteArray::remove(const int index) { + if (index < 0 || index >= bytes.size()) { + throw std::out_of_range("Index out of range"); + } + bytes.erase(bytes.begin() + index); +} + +size_t ByteArray::size() const { + return bytes.size(); +} + +void ByteArray::clear() { + bytes.clear(); +} + +void ByteArray::assign(char *buffer, const ByteHander size) { + bytes.assign(buffer, buffer + size); +} + +void ByteArray::assign(const void *buffer, const ByteHander size) { + const char* cstr = static_cast(buffer); + bytes.assign(cstr, cstr + size); +} + +bool ByteArray::IsEmpty() const { + return bytes.empty(); +} + +void ByteArray::append(const std::string& str) { + bytes.insert(bytes.end(), str.begin(), str.end()); +} + +void ByteArray::append(const ByteArray& str) { + bytes.insert(bytes.end(), str.bytes.begin(), str.bytes.end()); +} + +std::vector::iterator ByteArray::begin() { + return bytes.begin(); +} + +std::vector::iterator ByteArray::end() { + return bytes.end(); +} + +std::vector::const_iterator ByteArray::begin() const { + return bytes.begin(); +} + +std::vector::const_iterator ByteArray::end() const { + return bytes.end(); +} + +ByteArray ByteArray::fromString(const std::string &str) { + ByteArray byteArray; + for (const char c : str) { + byteArray.add(Byte(static_cast(c))); + } + return byteArray; +} + +std::string ByteArray::toString() const { + std::string result; + for (const Byte& byte : bytes) { + result += static_cast(byte.get()); + } + return result; +} + +std::vector ByteArray::toVector() { + return bytes; +} + +std::vector ByteArray::toVector() const{ + return bytes; +} + +char * ByteArray::buffer() { + return reinterpret_cast(bytes.data()); +} + +const char* ByteArray::buffer() const { + return reinterpret_cast(bytes.data()); +} + +char * ByteArray::newBuffer() const { + const auto str = new char[bytes.size() + 1]; + std::memcpy(str, bytes.data(), bytes.size()); + str[bytes.size()] = '\0'; + return str; +} + +void ByteArray::resize(const size_t len) { + bytes.resize(len); +} + +void ByteArray::operator=(const ByteArray &other) { + bytes = other.bytes; +} + +void ByteArray::operator=(const std::string &str) { + bytes.assign(str.begin(), str.end()); +} + +bool ByteArray::operator==(const ByteArray &other) const { + return bytes == other.bytes; +} + +bool ByteArray::operator!=(const ByteArray &other) const { + return bytes != other.bytes; +} + +void ByteArray::operator+=(const ByteArray &other) { + bytes.insert(bytes.end(), other.bytes.begin(), other.bytes.end()); +} + +void ByteArray::operator-=(const ByteArray &other) { + if (other.bytes.empty()) { + return; + } + + // 从当å‰å­—节数组中移除所有在other中出现的元素 + for (const auto& byte : other.bytes) { + bytes.erase(std::remove(bytes.begin(), bytes.end(), byte), bytes.end()); + } +} + +Byte& ByteArray::operator[](const int index) { + if (index < 0 || index >= bytes.size()) { + throw std::out_of_range("Index out of range"); + } + return *(bytes.data() + index); +} + +Byte ByteArray::operator[](const int index) const { + if (index < 0 || index >= bytes.size()) { + throw std::out_of_range("Index out of range"); + } + return *(bytes.data() + index); +} + +ByteArray ByteArray::subBuffer(const ByteHander start, const ByteHander end) const { + if (start > end || end > bytes.size()) { + throw std::out_of_range("subBuffer Index out of range"); + } + ByteArray ret(bytes.data() + start, end - start); + return ret; +} + +std::string ByteArray::toBase64() { + std::string ret; + int i = 0; + uint8_t char_array_3[3]; + uint8_t char_array_4[4]; + auto it = bytes.begin(); + while (it != bytes.end()) { + char_array_3[i++] = *(it++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (i = 0; (i < 4); i++) { + ret += base64_chars[char_array_4[i]]; + } + i = 0; + } + } + if (i) { + int j = 0; + for (j = i; j < 3; j++) { + char_array_3[j] = '\0'; + } + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) { + ret += base64_chars[char_array_4[j]]; + } + + while ((i++ < 3)) { + ret += '='; + } + } + return ret; +} + +ByteArray ByteArray::fromBase64(const std::string &base64Str) { + ByteArray result; + unsigned char char_array_4[4]; + unsigned char char_array_3[3]; + size_t i = 0; + size_t j = 0; + + auto it = base64Str.begin(); + while (it != base64Str.end() && *it != '=') { + // 跳过éžBase64字符 + if (*it == ' ' || *it == '\r' || *it == '\n') { + ++it; + continue; + } + + char_array_4[i++] = static_cast(*it); + ++it; + + if (i == 4) { + for (j = 0; j < 4; j++) { + char_array_4[j] = base64_decode_table[char_array_4[j]]; + } + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; j < 3; j++) { + result.add(Byte(char_array_3[j])); + } + i = 0; + } + } + + // 处ç†å‰©ä½™å­—符 + if (i > 0) { + for (j = i; j < 4; j++) { + char_array_4[j] = 0; + } + + for (j = 0; j < i; j++) { + char_array_4[j] = base64_decode_table[char_array_4[j]]; + } + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; j < i - 1; j++) { + result.add(Byte(char_array_3[j])); + } + } + + return result; +} + +void ByteArray::fill(const Byte value, const size_t start, size_t end) { + if (bytes.empty()) return; + + if (end == static_cast(-1)) { + end = bytes.size(); + } + + if (start >= bytes.size() || end > bytes.size() || start > end) { + throw std::out_of_range("Index out of range"); + } + + std::fill(bytes.begin() + start, bytes.begin() + end, value); +} + +void ByteArray::copyTo(ByteArray &dest, const size_t srcStart, const size_t destStart, size_t count) const { + if (bytes.empty()) return; + + if (srcStart >= bytes.size()) { + throw std::out_of_range("Source start index out of range"); + } + + if (count == static_cast(-1)) { + count = bytes.size() - srcStart; + } + + if (srcStart + count > bytes.size()) { + throw std::out_of_range("Copy count exceeds source size"); + } + + // ç¡®ä¿ç›®æ ‡æ•°ç»„有足够的空间 + if (destStart + count > dest.bytes.size()) { + dest.bytes.resize(destStart + count); + } + + // C++98兼容的实现:使用std::copy替代std::copy_n + std::copy(bytes.begin() + srcStart, + bytes.begin() + srcStart + count, + dest.bytes.begin() + destStart); +} + +ByteArray ByteArray::clone() const { + return ByteArray(*this); +} + +int ByteArray::indexOf(const Byte value, const size_t start) const { + if (bytes.empty() || start >= bytes.size()) { + return -1; + } + + const auto it = std::find(bytes.begin() + start, bytes.end(), value); + if (it != bytes.end()) { + return static_cast(std::distance(bytes.begin(), it)); + } + return -1; +} + +int ByteArray::lastIndexOf(const Byte value, size_t start) const { + if (bytes.empty()) { + return -1; + } + + if (start == static_cast(-1) || start >= bytes.size()) { + start = bytes.size() - 1; + } + + for (int i = static_cast(start); i >= 0; --i) { + if (bytes[i] == value) { + return i; + } + } + return -1; +} + +int ByteArray::indexOf(const ByteArray &pattern, const size_t start) const { + if (pattern.bytes.empty() || bytes.empty() || start >= bytes.size()) { + return -1; + } + + auto it = std::search(bytes.begin() + start, bytes.end(), + pattern.bytes.begin(), pattern.bytes.end()); + if (it != bytes.end()) { + return static_cast(std::distance(bytes.begin(), it)); + } + return -1; +} + +int ByteArray::lastIndexOf(const ByteArray &pattern, size_t start) const { + if (pattern.bytes.empty() || bytes.empty()) { + return -1; + } + + if (pattern.bytes.size() > bytes.size()) { + return -1; + } + + if (start == static_cast(-1) || start >= bytes.size()) { + start = bytes.size() - 1; + } + + // é™åˆ¶startç¡®ä¿ä¸ä¼šè¶Šç•Œ + if (start < pattern.bytes.size() - 1) { + return -1; + } + + size_t end = start - pattern.bytes.size() + 1; + for (int i = static_cast(start); i >= static_cast(end); --i) { + bool match = true; + for (size_t j = 0; j < pattern.bytes.size(); ++j) { + if (bytes[i - static_cast(pattern.bytes.size()) + 1 + j] != pattern.bytes[j]) { + match = false; + break; + } + } + if (match) { + return i - static_cast(pattern.bytes.size()) + 1; + } + } + return -1; +} + +bool ByteArray::equals(const ByteArray &other) const { + return *this == other; +} + diff --git a/CC_SDK_VS/base/CCByteArray.h b/CC_SDK_VS/base/CCByteArray.h new file mode 100644 index 0000000..658c0c5 --- /dev/null +++ b/CC_SDK_VS/base/CCByteArray.h @@ -0,0 +1,331 @@ +#ifndef CC_BYTEARRAY_H +#define CC_BYTEARRAY_H + +#include +#include "list" +#include "CCByte.h" +#include "../TL/AutoDestruct.h" + +typedef size_t ByteHander; // +#define HanderSize sizeof(ByteHander) + +namespace CTL { + /** + * ByteArray类用于处ç†å­—节数组,æä¾›å¤šç§æ–¹å¼çš„字节æ“作和转æ¢ã€‚ + */ + class ByteArray{ + std::vector bytes; + public: + ByteArray() = default; + /** + * 构造函数,从std::stringåˆå§‹åŒ–字节数组。 + * @param str 用于åˆå§‹åŒ–字节数组的字符串。 + */ + ByteArray(const std::string& str); + /** + * 构造函数,将结构体指针åˆå§‹åŒ–字节数组。 + * @param str 结构体指针。 + * @param size 结构体指针大å°ã€‚ + */ + ByteArray(const void* str, size_t size); + /** + * 构造函数,从C风格字符串åˆå§‹åŒ–字节数组。 + * @param str 用于åˆå§‹åŒ–字节数组的C风格字符串。 + */ + ByteArray(const char* str); + /** + * å¤åˆ¶æž„造函数,从å¦ä¸€ä¸ªByteArray对象åˆå§‹åŒ–字节数组。 + * @param other 用于åˆå§‹åŒ–çš„å¦ä¸€ä¸ªByteArray对象。 + */ + ByteArray(const ByteArray& other); + /** + * 构造函数,从std::vectoråˆå§‹åŒ–字节数组。 + * @param bytes 用于åˆå§‹åŒ–字节数组的vector。 + */ + ByteArray(const std::vector& bytes); + /** + * 构造函数,从std::liståˆå§‹åŒ–字节数组。 + * @param bytes 用于åˆå§‹åŒ–字节数组的list。 + */ + ByteArray(const std::list& bytes); + /** + * 构造函数,从Byte指针åˆå§‹åŒ–字节数组。 + * @param bytes 用于åˆå§‹åŒ–字节数组的Byte指针。 + */ + ByteArray(const Byte* bytes); + /** + * 构造函数,创建指定大å°çš„字节数组。 + * @param size è¦åˆ›å»ºçš„字节数组的大å°ã€‚ + */ + ByteArray(ByteHander size); + /** + * 添加一个字节到字节数组末尾。 + * @param byte è¦æ·»åŠ çš„å­—èŠ‚ã€‚ + */ + void add(Byte byte); + /** + * èŽ·å–æŒ‡å®šç´¢å¼•处的字节。 + * @param index 字节的索引。 + * @return 指定索引处的字节。 + */ + [[nodiscard]] Byte get(int index) const; + /** + * 设置指定索引处的字节。 + * @param index è¦è®¾ç½®å­—节的索引。 + * @param byte è¦è®¾ç½®çš„æ–°å­—节。 + */ + void set(int index, Byte byte); + /** + * 删除指定索引处的字节。 + * @param index è¦åˆ é™¤å­—节的索引。 + */ + void remove(int index); + /** + * 获å–字节数组的大å°ã€‚ + * @return 字节数组的大å°ã€‚ + */ + [[nodiscard]] size_t size() const; + /** + * 清空字节数组。 + */ + void clear(); + /** + * 用指定的缓冲区和大å°èµ‹å€¼å­—节数组。 + * @param buffer 指定的缓冲区。 + * @param size 缓冲区的大å°ã€‚ + */ + void assign(char * buffer, ByteHander size); + /** + * 用指定的缓冲区和大å°èµ‹å€¼å­—节数组。 + * @param buffer 指定的缓冲区。 + * @param size 缓冲区的大å°ã€‚ + */ + void assign(const void* buffer, ByteHander size); + /** + * 判断字节数组是å¦ä¸ºç©ºã€‚ + * @return 字节数组是å¦ä¸ºç©ºã€‚ + */ + [[nodiscard]] bool IsEmpty() const; + /** + * 在字节数组末尾追加一个字符串。 + * @param str è¦è¿½åŠ çš„å­—ç¬¦ä¸²ã€‚ + */ + void append(const std::string& str); + /** + * 在字节数组末尾追加å¦ä¸€ä¸ªå­—节数组。 + * @param str è¦è¿½åŠ çš„å­—èŠ‚æ•°ç»„ã€‚ + */ + void append(const ByteArray& str); + /** + * 返回字节数组的开始迭代器。 + * @return 字节数组的开始迭代器。 + */ + std::vector::iterator begin(); + /** + * 返回字节数组的结æŸè¿­ä»£å™¨ã€‚ + * @return 字节数组的结æŸè¿­ä»£å™¨ã€‚ + */ + std::vector::iterator end(); + /** + * 返回常é‡å­—节数组的开始迭代器。 + * @return 常é‡å­—节数组的开始迭代器。 + */ + std::vector::const_iterator begin() const; + /** + * 返回常é‡å­—节数组的结æŸè¿­ä»£å™¨ã€‚ + * @return 常é‡å­—节数组的结æŸè¿­ä»£å™¨ã€‚ + */ + std::vector::const_iterator end() const; + /** + * 从字符串创建字节数组。 + * @param str 用于创建字节数组的字符串。 + * @return 从字符串创建的字节数组。 + */ + static ByteArray fromString(const std::string& str); + /** + * 将字节数组转æ¢ä¸ºå­—符串。 + * @return 字节数组的字符串表示。 + */ + std::string toString() const; + /** + * 获å–字节数组的底层vector。 + * @return 字节数组的底层vector。 + */ + std::vector toVector(); + /** + * 获å–字节数组的底层vector。 + * @return 字节数组的底层vector。 + */ + std::vector toVector() const; + /** + * 获å–字节数组的缓冲区。 + * @return 字节数组的缓冲区。 + */ + char* buffer(); + /** + * 获å–字节数组的缓冲区。 + * @return 字节数组的缓冲区。 + */ + [[nodiscard]] const char* buffer() const; + /** + * 获å–字节数组的缓冲区。 + * @return 新创建的字节数组的缓冲区(éœ€è¦æ‰‹åŠ¨ç®¡ç†å†…å­˜) + */ + char* newBuffer() const; + /** + * 调整字节数组的大å°ã€‚ + * @param len 新的大å°ã€‚ + */ + void resize(size_t len); + /** + * 赋值è¿ç®—符é‡è½½ï¼Œç”¨äºŽå­—节数组之间的赋值。 + * @param other è¦èµ‹å€¼çš„å¦ä¸€ä¸ªå­—节数组。 + */ + void operator = (const ByteArray& other); + /** + * 赋值è¿ç®—符é‡è½½ï¼Œç”¨äºŽå­—符串到字节数组的赋值。 + * @param str è¦èµ‹å€¼çš„字符串。 + */ + void operator = (const std::string& str); + /** + * 比较è¿ç®—符é‡è½½ï¼Œç”¨äºŽæ¯”较两个字节数组是å¦ç›¸ç­‰ã€‚ + * @param other è¦æ¯”较的å¦ä¸€ä¸ªå­—节数组。 + * @return 如果两个字节数组相等则返回true,å¦åˆ™è¿”回false。 + */ + bool operator == (const ByteArray& other) const; + /** + * 比较è¿ç®—符é‡è½½ï¼Œç”¨äºŽæ¯”较两个字节数组是å¦ä¸ç›¸ç­‰ã€‚ + * @param other è¦æ¯”较的å¦ä¸€ä¸ªå­—节数组。 + * @return 如果两个字节数组ä¸ç›¸ç­‰åˆ™è¿”回true,å¦åˆ™è¿”回false。 + */ + bool operator != (const ByteArray& other) const; + /** + * 加法è¿ç®—符é‡è½½ï¼Œç”¨äºŽè¿½åŠ å¦ä¸€ä¸ªå­—节数组到当å‰å­—节数组末尾。 + * @param other è¦è¿½åŠ çš„å¦ä¸€ä¸ªå­—节数组。 + */ + void operator += (const ByteArray& other); + /** + * 凿³•è¿ç®—符é‡è½½ï¼Œç”¨äºŽä»Žå½“å‰å­—节数组中移除å¦ä¸€ä¸ªå­—节数组的内容。 + * @param other è¦ç§»é™¤çš„å¦ä¸€ä¸ªå­—节数组。 + */ + void operator -= (const ByteArray& other); + /** + * 索引è¿ç®—符é‡è½½ï¼Œç”¨äºŽèŽ·å–字节数组中的指定索引处的字节。 + * @param index è¦èŽ·å–的字节索引。 + * @return 指定索引处的字节。 + */ + Byte& operator [] (int index); + /** + * 索引è¿ç®—符é‡è½½ï¼Œç”¨äºŽèŽ·å–字节数组中的指定索引处的字节。 + * @param index è¦èŽ·å–的字节索引。 + * @return 指定索引处的字节。 + */ + Byte operator [] (int index) const; + /** + * 将字节数组转æ¢ä¸ºæŒ‡å®šç±»åž‹çš„æŒ‡é’ˆã€‚ + * @param other è¦è½¬æ¢çš„字节数组 + * @return 返回指å‘字节数组的指定类型的指针(éœ€è¦æ‰‹åŠ¨ç®¡ç†å†…å­˜) + */ + template + static T* Conversion(const ByteArray& other) { + const T* t_const = reinterpret_cast(other.newBuffer()); + T* t = const_cast(t_const); + return t; + } + /** + * 将字节数组转æ¢ä¸ºæŒ‡å®šç±»åž‹çš„æŒ‡é’ˆã€‚ + * @return 指å‘字节数组的指定类型的指针(RAII管ç†å†…å­˜) + */ + template + AutoDestruct Conversion() { + const T* t_const = reinterpret_cast(this->newBuffer()); + T* t = const_cast(t_const); + return CTL::AutoDestruct(t); + } + /** + * 将字节数组转æ¢ä¸ºæŒ‡å®šç±»åž‹çš„æŒ‡é’ˆã€‚ + * @param str è¦è½¬æ¢çš„字节数组 + * @param size 字节数组的长度 + * @return 返回指å‘字节数组的指定类型的指针(RAII管ç†å†…å­˜) + */ + template + void Conversion(T* str, const ByteHander size) { + const auto c_str = reinterpret_cast(str); + bytes.assign(c_str, c_str + size); + } + /** + * 获å–å­—èŠ‚æ•°ç»„çš„å­æ•°ç»„。 + * @param start å­æ•°ç»„的起始索引。 + * @param end å­æ•°ç»„的结æŸç´¢å¼•。 + * @return è¿”å›žå­æ•°ç»„。 + */ + [[nodiscard]] ByteArray subBuffer(ByteHander start, ByteHander end) const; + /** + * 将字节数组转æ¢ä¸ºBase64字符串。 + * @return Base64字符串。 + */ + std::string toBase64(); + /** + * å°†Base64字符串转æ¢ä¸ºå­—节数组。 + * @param base64Str Base64字符串。 + * @return 转æ¢åŽçš„字节数组。 + */ + static ByteArray fromBase64(const std::string& base64Str); + /** + * 将指定值填充到数组的æŸä¸ªèŒƒå›´ + * @param value è¦å¡«å……的值 + * @param start 起始索引 + * @param end 结æŸç´¢å¼•(ä¸åŒ…å«ï¼‰ + */ + void fill(Byte value, size_t start = 0, size_t end = -1); + /** + * å¤åˆ¶æ•°ç»„的一部分到å¦ä¸€ä¸ªByteArray + * @param dest 目标ByteArray + * @param srcStart æºèµ·å§‹ç´¢å¼• + * @param destStart 目标起始索引 + * @param count å¤åˆ¶çš„å…ƒç´ æ•°é‡ + */ + void copyTo(ByteArray& dest, size_t srcStart = 0, size_t destStart = 0, size_t count = -1) const; + /** + * 克隆当å‰ByteArray + * @return æ–°çš„ByteArray副本 + */ + ByteArray clone() const; + /** + * 查找特定字节第一次出现的ä½ç½® + * @param value è¦æŸ¥æ‰¾çš„字节 + * @param start èµ·å§‹æœç´¢ä½ç½® + * @return 找到的ä½ç½®ï¼Œæœªæ‰¾åˆ°è¿”回-1 + */ + int indexOf(Byte value, size_t start = 0) const; + /** + * 查找特定字节最åŽä¸€æ¬¡å‡ºçŽ°çš„ä½ç½® + * @param value è¦æŸ¥æ‰¾çš„字节 + * @param start èµ·å§‹æœç´¢ä½ç½® + * @return 找到的ä½ç½®ï¼Œæœªæ‰¾åˆ°è¿”回-1 + */ + int lastIndexOf(Byte value, size_t start = -1) const; + /** + * 查找字节åºåˆ—第一次出现的ä½ç½® + * @param pattern è¦æŸ¥æ‰¾çš„字节åºåˆ— + * @param start èµ·å§‹æœç´¢ä½ç½® + * @return 找到的ä½ç½®ï¼Œæœªæ‰¾åˆ°è¿”回-1 + */ + int indexOf(const ByteArray& pattern, size_t start = 0) const; + /** + * 查找字节åºåˆ—最åŽä¸€æ¬¡å‡ºçŽ°çš„ä½ç½® + * @param pattern è¦æŸ¥æ‰¾çš„字节åºåˆ— + * @param start èµ·å§‹æœç´¢ä½ç½® + * @return 找到的ä½ç½®ï¼Œæœªæ‰¾åˆ°è¿”回-1 + */ + int lastIndexOf(const ByteArray& pattern, size_t start = -1) const; + /** + * 比较两个ByteArray是å¦ç›¸ç­‰ + * @param other è¦æ¯”较的å¦ä¸€ä¸ªByteArray + * @return 如果相等返回true,å¦åˆ™è¿”回false + */ + bool equals(const ByteArray& other) const; + }; +} + +#endif diff --git a/CMakeLists.txt b/CMakeLists.txt index 22b4fcc..ba0ca65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,19 @@ -cmake_minimum_required(VERSION 4.0) +cmake_minimum_required(VERSION 3.0...4.0) project(WebSocket) set(CMAKE_CXX_STANDARD 98) add_executable(WebSocket main.cpp - WebSocket/CCWebSocket.cpp - WebSocket/CCWebSocket.h + CC_SDK_VS/WebSocket/CCWebSocket.cpp + CC_SDK_VS/WebSocket/CCWebSocket.h + CC_SDK_VS/CCMutex.cpp + CC_SDK_VS/CCThread.cpp + CC_SDK_VS/CCThreadPool.cpp + CC_SDK_VS/Socket/CCClientSocket.cpp + CC_SDK_VS/Socket/CCDatagramSocket.cpp + CC_SDK_VS/Socket/CCServerSocket.cpp + CC_SDK_VS/Socket/CCSocket.cpp + CC_SDK_VS/base/CCByteArray.cpp + CC_SDK_VS/TL/AutoDestruct.h )