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}; + // 閬嶅巻鎵鏈夊湴鍧淇℃伅骞舵墦鍗癐Pv4鍦板潃 + for (struct addrinfo* p = info; p != NULL; p = p->ai_next) { + void* addr; + + // 瀵逛簬IPv4锛屼娇鐢╥pv4_mapping鏉ュ吋瀹笽Pv6鍦板潃 + 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) { // 妫鏌ュ畠鏄惁涓篒Pv4 + 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鍦板潃锛屽皾璇旸NS瑙f瀽 + 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 瑙f瀽 + 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鍦板潃锛屽皾璇旸NS瑙f瀽 + 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 瑙f瀽 + 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 = {};// 淇濆瓨瀹㈡埛绔疘P鍦板潃绔彛 + 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 = {};// 淇濆瓨瀹㈡埛绔疘P鍦板潃绔彛 + 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; + + // 濡傛灉鏄疘P鍦板潃鏍煎紡锛岀洿鎺ヨ繑鍥 + if (host.find('.') != std::string::npos) { + addresses.push_back(host); + return addresses; + } + + // 杩欓噷搴旇瀹炵幇DNS瑙f瀽锛岀畝鍖栧鐞 + // 瀹為檯瀹炵幇涓渶瑕佽皟鐢╣etaddrinfo绛夌郴缁熷嚱鏁 + 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骞冲彴涓媁SA鍒濆鍖栦笌娓呯悊绫 +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(); + // 鏋勯犲嚱鏁帮紝鍒濆鍖朣ocket + Socket(SOCKET sock); + // 鍒濆鍖朣ocket骞惰缃睘鎬 + bool Init(IPVX IPV4orIPV6, TORU TCPorUDP, TYPE Type = TYPE::STREAM); + // 鑾峰彇Socket鍙ユ焺 + SOCKET GetSOCKET() const; + // 璁剧疆Socket閫夐」 + bool SetSockOpt(CCOpt opt) const; + // 璁剧疆Socket涓洪潪闃诲妯″紡 + void SetSocketNonBlocking() const; + // 妫鏌ocket鏄惁鏈夊彲鐢ㄦ暟鎹 + 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; + // 閲嶈浇涓嶇瓑鍙疯繍绠楃锛屾瘮杈僑ocket瀵硅薄鏄惁涓嶇瓑 + bool operator != (Socket socket) const; + // 妫鏌ヨ繛鎺ユ槸鍚︽湁鏁 + bool isConnectionAlive() const; + // 妫鏌ocket鏄惁鍙啓 + 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); + // 鏍规嵁涓绘満鍚嶈幏鍙朓netAddress瀵硅薄 + 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; + // 鑾峰彇浠绘剰鍦板潃 (鐩稿綋浜嶫ava涓殑InetAddress.getByName("0.0.0.0")) + static InetAddress getAnyAddress(); + // 鑾峰彇鍥炵幆鍦板潃 (鐩稿綋浜嶫ava涓殑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); // 灏嗚凯浠e櫒绉诲姩鍒版寚瀹氱储寮 + *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); // 灏嗚凯浠e櫒绉诲姩鍒版寚瀹氱储寮 + _mutex.unlock(); // 瑙i攣 + return &(*it); // 杩斿洖鍏冪礌鐨勬寚閽堬紙鍘熶唬鐮佽繑鍥 it 鏄敊璇殑锛屽簲杩斿洖鎸囧悜瀵硅薄鐨勬寚閽堬級 + } + else { + _mutex.unlock(); // 瑙i攣 + 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涓嶅瓨鍦ㄦ垨鑰卽ncle涓洪粦 + 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 != '=') { + // 璺宠繃闈濨ase64瀛楃 + 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; + /** + * 鏋勯犲嚱鏁帮紝浠巗td::string鍒濆鍖栧瓧鑺傛暟缁勩 + * @param str 鐢ㄤ簬鍒濆鍖栧瓧鑺傛暟缁勭殑瀛楃涓层 + */ + ByteArray(const std::string& str); + /** + * 鏋勯犲嚱鏁帮紝灏嗙粨鏋勪綋鎸囬拡鍒濆鍖栧瓧鑺傛暟缁勩 + * @param str 缁撴瀯浣撴寚閽堛 + * @param size 缁撴瀯浣撴寚閽堝ぇ灏忋 + */ + ByteArray(const void* str, size_t size); + /** + * 鏋勯犲嚱鏁帮紝浠嶤椋庢牸瀛楃涓插垵濮嬪寲瀛楄妭鏁扮粍銆 + * @param str 鐢ㄤ簬鍒濆鍖栧瓧鑺傛暟缁勭殑C椋庢牸瀛楃涓层 + */ + ByteArray(const char* str); + /** + * 澶嶅埗鏋勯犲嚱鏁帮紝浠庡彟涓涓狟yteArray瀵硅薄鍒濆鍖栧瓧鑺傛暟缁勩 + * @param other 鐢ㄤ簬鍒濆鍖栫殑鍙︿竴涓狟yteArray瀵硅薄銆 + */ + ByteArray(const ByteArray& other); + /** + * 鏋勯犲嚱鏁帮紝浠巗td::vector鍒濆鍖栧瓧鑺傛暟缁勩 + * @param bytes 鐢ㄤ簬鍒濆鍖栧瓧鑺傛暟缁勭殑vector銆 + */ + ByteArray(const std::vector& bytes); + /** + * 鏋勯犲嚱鏁帮紝浠巗td::list鍒濆鍖栧瓧鑺傛暟缁勩 + * @param bytes 鐢ㄤ簬鍒濆鍖栧瓧鑺傛暟缁勭殑list銆 + */ + ByteArray(const std::list& bytes); + /** + * 鏋勯犲嚱鏁帮紝浠嶣yte鎸囬拡鍒濆鍖栧瓧鑺傛暟缁勩 + * @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); + /** + * 杩斿洖瀛楄妭鏁扮粍鐨勫紑濮嬭凯浠e櫒銆 + * @return 瀛楄妭鏁扮粍鐨勫紑濮嬭凯浠e櫒銆 + */ + std::vector::iterator begin(); + /** + * 杩斿洖瀛楄妭鏁扮粍鐨勭粨鏉熻凯浠e櫒銆 + * @return 瀛楄妭鏁扮粍鐨勭粨鏉熻凯浠e櫒銆 + */ + std::vector::iterator end(); + /** + * 杩斿洖甯搁噺瀛楄妭鏁扮粍鐨勫紑濮嬭凯浠e櫒銆 + * @return 甯搁噺瀛楄妭鏁扮粍鐨勫紑濮嬭凯浠e櫒銆 + */ + std::vector::const_iterator begin() const; + /** + * 杩斿洖甯搁噺瀛楄妭鏁扮粍鐨勭粨鏉熻凯浠e櫒銆 + * @return 甯搁噺瀛楄妭鏁扮粍鐨勭粨鏉熻凯浠e櫒銆 + */ + std::vector::const_iterator end() const; + /** + * 浠庡瓧绗︿覆鍒涘缓瀛楄妭鏁扮粍銆 + * @param str 鐢ㄤ簬鍒涘缓瀛楄妭鏁扮粍鐨勫瓧绗︿覆銆 + * @return 浠庡瓧绗︿覆鍒涘缓鐨勫瓧鑺傛暟缁勩 + */ + static ByteArray fromString(const std::string& str); + /** + * 灏嗗瓧鑺傛暟缁勮浆鎹负瀛楃涓层 + * @return 瀛楄妭鏁扮粍鐨勫瓧绗︿覆琛ㄧず銆 + */ + std::string toString() const; + /** + * 鑾峰彇瀛楄妭鏁扮粍鐨勫簳灞倂ector銆 + * @return 瀛楄妭鏁扮粍鐨勫簳灞倂ector銆 + */ + std::vector toVector(); + /** + * 鑾峰彇瀛楄妭鏁扮粍鐨勫簳灞倂ector銆 + * @return 瀛楄妭鏁扮粍鐨勫簳灞倂ector銆 + */ + 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 濡傛灉涓や釜瀛楄妭鏁扮粍鐩哥瓑鍒欒繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse銆 + */ + bool operator == (const ByteArray& other) const; + /** + * 姣旇緝杩愮畻绗﹂噸杞斤紝鐢ㄤ簬姣旇緝涓や釜瀛楄妭鏁扮粍鏄惁涓嶇浉绛夈 + * @param other 瑕佹瘮杈冪殑鍙︿竴涓瓧鑺傛暟缁勩 + * @return 濡傛灉涓や釜瀛楄妭鏁扮粍涓嶇浉绛夊垯杩斿洖true锛屽惁鍒欒繑鍥瀎alse銆 + */ + 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(); + /** + * 灏咮ase64瀛楃涓茶浆鎹负瀛楄妭鏁扮粍銆 + * @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); + /** + * 澶嶅埗鏁扮粍鐨勪竴閮ㄥ垎鍒板彟涓涓狟yteArray + * @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 瑕佹瘮杈冪殑鍙︿竴涓狟yteArray + * @return 濡傛灉鐩哥瓑杩斿洖true锛屽惁鍒欒繑鍥瀎alse + */ + 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 )