diff --git a/engine2.0/engine2.0/Depends/include/HttpClientS.hpp b/engine2.0/engine2.0/Depends/include/HttpClientS.hpp index a33be225fd9d3c946a78c2811071641ddba64556..29468a761b5d7a055fcdacbf621991753ad5a30d 100644 --- a/engine2.0/engine2.0/Depends/include/HttpClientS.hpp +++ b/engine2.0/engine2.0/Depends/include/HttpClientS.hpp @@ -355,7 +355,7 @@ namespace doyou { WriteResponse("404 Not Found", "(^o^): 404!", 11); } - // + // 数据应答-OK void Resp200OK(const char* bodyBuff, int bodyLen) { WriteResponse("200 OK", bodyBuff, bodyLen); diff --git a/engine2.0/engine2.0/Depends/include/SelectServer.hpp b/engine2.0/engine2.0/Depends/include/SelectServer.hpp index 5283c09196eb5fd01900848b9b372a03413e611d..403f4b3392970b428c80ed9b0ad2d796c8fc1cc3 100644 --- a/engine2.0/engine2.0/Depends/include/SelectServer.hpp +++ b/engine2.0/engine2.0/Depends/include/SelectServer.hpp @@ -1,7 +1,8 @@ #ifndef _CELL_SELECT_SERVER_HPP_ #define _CELL_SELECT_SERVER_HPP_ -#include"Server.hpp" +// [2024-7-4-ok] +#include "Server.hpp" #include // 重复包含没有关系,因为存在宏校验,尽量避免重复包含相同头文件 @@ -15,7 +16,7 @@ namespace doyou { class SelectServer : public Server { public: - // 在释放子类对象时,就先自己关闭onrun执行线程,就不会出现onrun线程在当前对象析构后还来调用当前类对象的方法了(会直接出错) + // 分析:在释放子类对象时,就先自己关闭onrun执行线程,就不会出现onrun线程在当前对象析构后还来调用当前类对象的方法了(会直接出错),对象已析构,再调用对象方法或属性会直接导致程序报错。 ~SelectServer() { Close(); // 调用之后会关闭onrun函数所在执行线程 @@ -74,11 +75,12 @@ namespace doyou { } } - ///nfds 是一个整数值 是指fd_set集合中所有描述符(socket)的范围,而不是数量 - ///既是所有文件描述符最大值+1 在Windows中这个参数可以写0 + /// nfds 是一个整数值 是指fd_set集合中所有描述符(socket)的范围,而不是数量 + /// 既是所有文件描述符最大值+1 在Windows中这个参数可以写0 timeval t{ 0, 1 }; // 结构体初始化方式 int ret = 0; // 可写入集合校验,在无数据可写的时候可写入集合为空,阻塞会生效,可以节省系统资源开销 + // 分析:采用select网络通信模型非阻塞模式,有事件函数立刻执行结束,没有事件阻塞到指定时间后,函数执行返回,不会一直阻塞在此行 if (bNeedWrite) { ret = select(_maxSock + 1, _fdRead.fdset(), _fdWrite.fdset(), nullptr, &t); @@ -100,8 +102,10 @@ namespace doyou { { return true; } + ReadData(); WriteData(); + return true; } diff --git a/engine2.0/engine2.0/Depends/include/Server.hpp b/engine2.0/engine2.0/Depends/include/Server.hpp index 7815b466bcce909145519b270972f51ea98f745f..105de0465113c8f7ed837a7fb623a575ca8ea444 100644 --- a/engine2.0/engine2.0/Depends/include/Server.hpp +++ b/engine2.0/engine2.0/Depends/include/Server.hpp @@ -46,7 +46,7 @@ namespace doyou { _pNetEvent = event; } - //关闭Socket + // 关闭Socket void Close() { CELLLog_Info("Server%d.Close begin", _id); @@ -199,10 +199,11 @@ namespace doyou { void addClient(Client* pClient) { + // 分析:采用自解锁可以避免出现死锁情况 std::lock_guard lock(_mutex); - //_mutex.lock(); + // _mutex.lock(); _clientsBuff.push_back(pClient); - //_mutex.unlock(); + // _mutex.unlock(); } void Start() @@ -271,7 +272,7 @@ namespace doyou { protected: // int _id = -1; - //客户列表是否有变化 + // 客户列表是否有变化 bool _clients_change = true; diff --git a/engine2.0/engine2.0/Depends/include/TcpHttpServer.hpp b/engine2.0/engine2.0/Depends/include/TcpHttpServer.hpp index a32568e52d08db058adcada2173b9b1fa531f657..5d285274f8f86f6713d8b06edfdd152405d72693 100644 --- a/engine2.0/engine2.0/Depends/include/TcpHttpServer.hpp +++ b/engine2.0/engine2.0/Depends/include/TcpHttpServer.hpp @@ -1,6 +1,7 @@ #ifndef _DOYOU_IO_TCP_HTTP_SERVER_HPP_ #define _DOYOU_IO_TCP_HTTP_SERVER_HPP_ +// [2024-6-30-ok] // 分析:文件包含顺序不对会导致编译错误。 // 需要,先包含[TcpServerMgr.hpp], 再包含[HttpClient.hpp], 反之编译报错。 // 原因,文件[TcpServerMgr.hpp]定义宏[CELL_USE_IOCP], 文件[HttpClient.hpp]使用宏[CELL_USE_IOCP]。 @@ -10,7 +11,7 @@ namespace doyou { namespace io { - // 可使用服务模型(三自选一):1-TcpSelectServer 2-TcpEpollServer 3-TcpIocpServer + // 可使用服务模型(三选一):1-TcpSelectServer 2-TcpEpollServer 3-TcpIocpServer class TcpHttpServer : public TcpServerMgr // 根据不同操作系统自动选择最佳网络通信模型 { public: diff --git a/engine2.0/engine2.0/Depends/include/TcpSelectServer.hpp b/engine2.0/engine2.0/Depends/include/TcpSelectServer.hpp index b503eb79f804046f87c25351b69b1bb91752f9bb..faa2ed4b86af2c991bef3264be46c7329924a176 100644 --- a/engine2.0/engine2.0/Depends/include/TcpSelectServer.hpp +++ b/engine2.0/engine2.0/Depends/include/TcpSelectServer.hpp @@ -1,6 +1,7 @@ #ifndef _EasySelectServer_hpp_ #define _EasySelectServer_hpp_ +// [2024-6-30-ok] #include "TcpServer.hpp" #include "SelectServer.hpp" @@ -38,7 +39,7 @@ namespace doyou { /// nfds 是一个整数值 是指fd_set集合中所有描述符(socket)的范围,而不是数量 /// para1-既是所有文件描述符最大值+1 在Windows中这个参数可以写0 timeval t = { 0, 1 }; - int ret = select(Sockfd() + 1, fdRead.fdset(), 0, 0, &t); // + int ret = select(Sockfd() + 1, fdRead.fdset(), 0, 0, &t); // no block model if (ret < 0) { if (errno == EINTR) { // 处理可能出现的系统终端导致的程序终止 diff --git a/engine2.0/engine2.0/Depends/include/TcpServer.hpp b/engine2.0/engine2.0/Depends/include/TcpServer.hpp index 4727d5fda69ec0b327eef01e39b3884cf39f4d57..37937d8b9a8267a67054588089926d3deba08bfe 100644 --- a/engine2.0/engine2.0/Depends/include/TcpServer.hpp +++ b/engine2.0/engine2.0/Depends/include/TcpServer.hpp @@ -1,19 +1,20 @@ #ifndef _EasyTcpServer_hpp_ #define _EasyTcpServer_hpp_ -#include"CELL.hpp" -#include"Client.hpp" -#include"Server.hpp" -#include"INetEvent.hpp" -#include"NetWork.hpp" -#include"Config.hpp" +// [2024-7-4-ok] +#include "CELL.hpp" +#include "Client.hpp" +#include "Server.hpp" +#include "INetEvent.hpp" +#include "NetWork.hpp" +#include "Config.hpp" // 分析:项目中不必要的头文件不要包含进来,会增大可执行文件大小 -//#include"FDSet.hpp" // 封装的fd_set集合 +//#include "FDSet.hpp" // 封装的fd_set集合 -#include -#include -#include +#include +#include +#include namespace doyou { namespace io { // 增加两层命令空间,避免在其它项目应用时类名出现冲突 @@ -25,7 +26,7 @@ namespace doyou { // Thread _thread; // 消息处理对象,内部会创建线程 - std::vector _cellServers; + std::vector _cellServers; // 动态数组数据类型为指针,避免栈爆炸 // 每秒消息计时 Timestamp _tTime; // 服务端套接字,功能:接收新的客户端加入 @@ -61,10 +62,12 @@ namespace doyou { _nRecvBuffSize = Config::Instance().getInt("nRecvBuffSize", RECV_BUFF_SZIE); _nMaxClient = Config::Instance().getInt("nMaxClient", FD_SETSIZE); } - virtual ~TcpServer() + + virtual ~TcpServer() // 虚析构函数作用:避免可能出现的内存泄露 { Close(); } + // 初始化Socket(服务端程序) SOCKET InitSocket(int af = AF_INET) // 参数默认值-IPV4 { @@ -86,6 +89,7 @@ namespace doyou { NetWork::make_reuseaddr(_sock); // 暂时注释,测试打印错误信息 CELLLog_Info("create socket<%d> success...", (int)_sock); } + return _sock; } @@ -100,7 +104,7 @@ namespace doyou { sin.sin_port = htons(port); // host to net unsigned short #ifdef _WIN32 // 采用宏来区分window和linux系统 - if (ip){ + if (ip) { sin.sin_addr.S_un.S_addr = inet_addr(ip); } else { @@ -147,7 +151,7 @@ namespace doyou { return ret; } - //监听端口号 + // 监听端口号 int Listen(int n) { // 3 listen 监听网络端口 @@ -159,6 +163,7 @@ namespace doyou { else { CELLLog_Info("listen port<%d> success...", _sock); } + return ret; } @@ -266,14 +271,14 @@ namespace doyou { } // 创建client对象 - virtual Client* MakeClientObj(SOCKET cSock) // 虚方法方便子类进行函数重写 + virtual Client* MakeClientObj(SOCKET cSock) // 虚方法方便子类进行函数重写,虚方法可实现多态 { return new Client(cSock, _nSendBuffSize, _nRecvBuffSize); } void addClientToCELLServer(Client* pClient) { - //查找客户数量最少的Server消息处理对象 + // 查找客户数量最少的Server消息处理对象 auto pMinServer = _cellServers[0]; for (auto pServer : _cellServers) { @@ -282,10 +287,11 @@ namespace doyou { pMinServer = pServer; } } + pMinServer->addClient(pClient); } - // 函数模型:区分使用SelectServer和EpollServer + // 函数模板:区分使用SelectServer和EpollServer template void Start(int nCELLServer) { @@ -296,9 +302,9 @@ namespace doyou { ser->SetClientNum(_nMaxClient / nCELLServer + 1); // +1兼容没整除存在余数的场景 _cellServers.push_back(ser); - //注册网络事件接受对象 + // 注册网络事件接受对象 ser->setEventObj(this); - //启动消息处理线程 + // 启动消息处理线程 ser->Start(); } _thread.Start(nullptr, @@ -307,7 +313,7 @@ namespace doyou { }); } - //关闭Socket + // 关闭Socket void Close() { CELLLog_Info("TcpServer.Close begin"); @@ -316,8 +322,10 @@ namespace doyou { { for (auto s : _cellServers) { - delete s; + delete s; // new/delete配套使用,释放内存 + s = nullptr; // 避免出现野指针 } + _cellServers.clear(); NetWork::destroy_socket(_sock); _sock = INVALID_SOCKET; diff --git a/engine2.0/engine2.0/Depends/include/TcpServerMgr.hpp b/engine2.0/engine2.0/Depends/include/TcpServerMgr.hpp index 7b41df852b68dc63ab2f02bbf2acc6f1b2fac0b3..ae355c045574b9bbbedf535bac4f012584402c4a 100644 --- a/engine2.0/engine2.0/Depends/include/TcpServerMgr.hpp +++ b/engine2.0/engine2.0/Depends/include/TcpServerMgr.hpp @@ -1,6 +1,7 @@ #ifndef _EasyServerMgr_hpp_ #define _EasyServerMgr_hpp_ +// [2024-6-30-ok] // 在不同操作系统下面选择最佳网络通信模型 #if _WIN32 // windows系统下面会定义此宏 #include "TcpIocpServer.hpp" // using iocp, only windows. diff --git a/engine2.0/engine2.0/Depends/include/Thread.hpp b/engine2.0/engine2.0/Depends/include/Thread.hpp index 01a96824b8a052d371a7ddd9245ab79a7bd8a9e4..56a5af44fefc92b83de2ecaa1928f8c0fbe997f9 100644 --- a/engine2.0/engine2.0/Depends/include/Thread.hpp +++ b/engine2.0/engine2.0/Depends/include/Thread.hpp @@ -41,7 +41,7 @@ namespace doyou { } } - //关闭线程 + // 关闭线程 void Close() { std::lock_guard lock(_mutex); diff --git a/engine2.0/engine2.0/Depends/include/TimeStamp.hpp b/engine2.0/engine2.0/Depends/include/TimeStamp.hpp index 93ac659b44a9b70acb6773d8b9933fc03b9824f7..530b76bb6408cd5d3774e5b05779259b5a9ae1db 100644 --- a/engine2.0/engine2.0/Depends/include/TimeStamp.hpp +++ b/engine2.0/engine2.0/Depends/include/TimeStamp.hpp @@ -30,7 +30,7 @@ namespace doyou { ~Timestamp() {} - void update() + void update() { //QueryPerformanceCounter(&_startCount); _begin = high_resolution_clock::now(); diff --git a/engine2.0/engine2.0/Depends/include/base64.hpp b/engine2.0/engine2.0/Depends/include/base64.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0fbb59cfb169e19f9acb0deaf4590d2985863777 --- /dev/null +++ b/engine2.0/engine2.0/Depends/include/base64.hpp @@ -0,0 +1,105 @@ +#ifndef _BASE64_H +#define _BASE64_H + +#include + +namespace doyou { + namespace io { + + static const std::string base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + + static inline bool IsBase64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); + } + + std::string Base64Encode(unsigned char const* bytes_to_encode, unsigned int in_len) { + std::string ret; + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (3 == i) { + 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) { + 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; + + } + + std::string Base64Decode(std::string const& encoded_string) { + std::size_t in_len = encoded_string.size(); + int i = 0; + int j = 0; + int in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::string ret; + + while (in_len-- && (encoded_string[in_] != '=') && IsBase64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; in_++; + if (4 == i) { + for (i = 0; i < 4; i++) + char_array_4[i] = base64_chars.find(char_array_4[i]); + + 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 (i = 0; (i < 3); i++) + ret += char_array_3[i]; + i = 0; + } + } + + if (i) { + for (j = i; j < 4; j++) + char_array_4[j] = 0; + + for (j = 0; j < 4; j++) + char_array_4[j] = base64_chars.find(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++) ret += char_array_3[j]; + } + + return ret; + } + + } +} + +#endif //#define _BASE64_H diff --git a/engine2.0/engine2.0/Depends/include/sha1.hpp b/engine2.0/engine2.0/Depends/include/sha1.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cef599e615d694f217563a6b4ec5036d28ee0b31 --- /dev/null +++ b/engine2.0/engine2.0/Depends/include/sha1.hpp @@ -0,0 +1,362 @@ +/* +Copyright (c) 2006-2017 by Jakob Schröter +This file is part of the gloox library. http://camaya.net/gloox + +This software is distributed under a license. The full license +agreement can be found in the file LICENSE in this distribution. +This software may not be copied, modified, sold or distributed +other than expressed in the named license agreement. + +This software is distributed without any warranty. +*/ + +#ifndef SHA_H__ +#define SHA_H__ + +#include + +namespace gloox +{ + + /** + * @brief An implementation of SHA1. + * + * @author Jakob Schröter + * @since 0.9 + */ + class SHA + { + + public: + /** + * Constructs a new SHA object. + */ + SHA(); + + /** + * Virtual Destructor. + */ + virtual ~SHA(); + + /** + * Resets the internal state. + */ + void reset(); + + /** + * Finalizes the hash computation. + */ + void finalize(); + + /** + * Returns the message digest in hex notation. Finalizes the hash if finalize() + * has not been called before. + * @return The message digest. + */ + const std::string hex(); + + /** + * Returns the raw binary message digest. Finalizes the hash if finalize() + * has not been called before. + * @return The message raw binary digest. + */ + const std::string binary(); + + /** + * Provide input to SHA1. + * @param data The data to compute the digest of. + * @param length The size of the data in bytes. + */ + void feed(const unsigned char* data, unsigned length); + + /** + * Provide input to SHA1. + * @param data The data to compute the digest of. + */ + void feed(const std::string& data); + + private: + void process(); + void pad(); + inline unsigned shift(int bits, unsigned word); + void init(); + + unsigned H[5]; + unsigned Length_Low; + unsigned Length_High; + unsigned char Message_Block[64]; + int Message_Block_Index; + bool m_finished; + bool m_corrupted; + + }; + +} + + +/* +Copyright (c) 2006-2017 by Jakob Schröter +This file is part of the gloox library. http://camaya.net/gloox + +This software is distributed under a license. The full license +agreement can be found in the file LICENSE in this distribution. +This software may not be copied, modified, sold or distributed +other than expressed in the named license agreement. + +This software is distributed without any warranty. +*/ + +#include + +namespace gloox +{ + + SHA::SHA() + { + init(); + } + + SHA::~SHA() + { + } + + void SHA::init() + { + Length_Low = 0; + Length_High = 0; + Message_Block_Index = 0; + + H[0] = 0x67452301; + H[1] = 0xEFCDAB89; + H[2] = 0x98BADCFE; + H[3] = 0x10325476; + H[4] = 0xC3D2E1F0; + + m_finished = false; + m_corrupted = false; + } + + void SHA::reset() + { + init(); + } + + const std::string SHA::hex() + { + if (m_corrupted) + return ""; + + if (!m_finished) + finalize(); + + char buf[41]; + for (int i = 0; i < 20; ++i) + sprintf(buf + i * 2, "%02x", static_cast(H[i >> 2] >> ((3 - (i & 3)) << 3))); + + return std::string(buf, 40); + } + + const std::string SHA::binary() + { + if (!m_finished) + finalize(); + + unsigned char digest[20]; + for (int i = 0; i < 20; ++i) + digest[i] = static_cast(H[i >> 2] >> ((3 - (i & 3)) << 3)); + + return std::string(reinterpret_cast(digest), 20); + } + + void SHA::finalize() + { + if (!m_finished) + { + pad(); + m_finished = true; + } + } + + void SHA::feed(const unsigned char* data, unsigned length) + { + if (!length) + return; + + if (m_finished || m_corrupted) + { + m_corrupted = true; + return; + } + + while (length-- && !m_corrupted) + { + Message_Block[Message_Block_Index++] = (*data & 0xFF); + + Length_Low += 8; + Length_Low &= 0xFFFFFFFF; + if (Length_Low == 0) + { + Length_High++; + Length_High &= 0xFFFFFFFF; + if (Length_High == 0) + { + m_corrupted = true; + } + } + + if (Message_Block_Index == 64) + { + process(); + } + + ++data; + } + } + + void SHA::feed(const std::string& data) + { + feed(reinterpret_cast(data.c_str()), static_cast(data.length())); + } + + void SHA::process() + { + const unsigned K[] = { 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; + unsigned temp; + unsigned W[80]; + unsigned A, B, C, D, E; + + for (t = 0; t < 16; t++) + { + W[t] = static_cast(Message_Block[t * 4]) << 24; + W[t] |= static_cast(Message_Block[t * 4 + 1]) << 16; + W[t] |= static_cast(Message_Block[t * 4 + 2]) << 8; + W[t] |= static_cast(Message_Block[t * 4 + 3]); + } + + for (t = 16; t < 80; ++t) + { + W[t] = shift(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); + } + + A = H[0]; + B = H[1]; + C = H[2]; + D = H[3]; + E = H[4]; + + for (t = 0; t < 20; ++t) + { + temp = shift(5, A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = shift(30, B); + B = A; + A = temp; + } + + for (t = 20; t < 40; ++t) + { + temp = shift(5, A) + (B ^ C ^ D) + E + W[t] + K[1]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = shift(30, B); + B = A; + A = temp; + } + + for (t = 40; t < 60; ++t) + { + temp = shift(5, A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = shift(30, B); + B = A; + A = temp; + } + + for (t = 60; t < 80; ++t) + { + temp = shift(5, A) + (B ^ C ^ D) + E + W[t] + K[3]; + temp &= 0xFFFFFFFF; + E = D; + D = C; + C = shift(30, B); + B = A; + A = temp; + } + + H[0] = (H[0] + A) & 0xFFFFFFFF; + H[1] = (H[1] + B) & 0xFFFFFFFF; + H[2] = (H[2] + C) & 0xFFFFFFFF; + H[3] = (H[3] + D) & 0xFFFFFFFF; + H[4] = (H[4] + E) & 0xFFFFFFFF; + + Message_Block_Index = 0; + } + + void SHA::pad() + { + Message_Block[Message_Block_Index++] = 0x80; + + if (Message_Block_Index > 56) + { + while (Message_Block_Index < 64) + { + Message_Block[Message_Block_Index++] = 0; + } + + process(); + } + + while (Message_Block_Index < 56) + { + Message_Block[Message_Block_Index++] = 0; + } + + Message_Block[56] = static_cast((Length_High >> 24) & 0xFF); + Message_Block[57] = static_cast((Length_High >> 16) & 0xFF); + Message_Block[58] = static_cast((Length_High >> 8) & 0xFF); + Message_Block[59] = static_cast((Length_High) & 0xFF); + Message_Block[60] = static_cast((Length_Low >> 24) & 0xFF); + Message_Block[61] = static_cast((Length_Low >> 16) & 0xFF); + Message_Block[62] = static_cast((Length_Low >> 8) & 0xFF); + Message_Block[63] = static_cast((Length_Low) & 0xFF); + + process(); + } + + + unsigned SHA::shift(int bits, unsigned word) + { + return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32 - bits)); + } + +} +namespace doyou { + namespace io { + static int SHA1_String(const unsigned char* inputString, unsigned long len, unsigned char* pOutSHA1Buf) + { + if (!inputString || !pOutSHA1Buf) + return -1; + + gloox::SHA sha1; + sha1.feed(inputString, len); + std::string s1 = sha1.binary(); + if (s1.length() != 20) + return -2; + + memcpy(pOutSHA1Buf, s1.c_str(), 20); + + return 1; + } + } +} +#endif // SHA_H__ diff --git a/engine2.0/engine2.0/Doc/Record.txt b/engine2.0/engine2.0/Doc/Record.txt index 4205bca3a93a768b7d4d29e1cf9e420b90c7b979..fb42d3d6fd8fbd99af6f24f443b83c7c4b8bf3d8 100644 --- a/engine2.0/engine2.0/Doc/Record.txt +++ b/engine2.0/engine2.0/Doc/Record.txt @@ -1035,6 +1035,41 @@ engine2.0: 构建项目整体的服务端架构,服务端不同模块间,服 1)增加计算机去部署相同的业务的同一服务器。换言之,同一服务去多态计算机上重复部署,以提高服务承载量。 2)易于计算。增加用户,应该增加匹配的服务器。 +【188】集群与分布式部署服务器系统后,高并发的能力会有很大提高。 + +【189】代理服务器特点总结: +1)提高访问效率,临时缓冲数据,便于访问。当前,可以将此项功能采用分布式设计思维将此业务分离出来为一个独立的服务器来做。 +2)提供防火墙作用,保护服务器信息安全。客户端只知道网关服务器,并不知道内网的服务器信息; +3)突破访问限制。内部服务器可以通过网关服务器,实现一些被限制的访问等。 + +【189】服务者消费者设计区别:服务者进行服务注册,提供服务。消费者进行服务发现,消费服务。 + +【190】websocket通信握手过程:websocket客户端发送http消息,请求升级通信协议为websocket通信, +websocket服务端收到消息后对其key键值按计算公式加密后,进行数据应答。websocket客户端收到消息后 +进行校验,校验通过,即成功建立websocket通信前的握手过程。 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine2.0/engine2.0/EasyHttpClient/client.cpp b/engine2.0/engine2.0/EasyHttpClient/client.cpp index ad3d109d1751dec0c1af0886619f55e380837da1..510d9c0a290e7338937512177c52545cca5309b5 100644 --- a/engine2.0/engine2.0/EasyHttpClient/client.cpp +++ b/engine2.0/engine2.0/EasyHttpClient/client.cpp @@ -1,5 +1,5 @@ // ǰhttpclient(׵webͻ) - +// [2024-6-23-ok] #include "Config.hpp" #include "TcpHttpClient.hpp" @@ -16,7 +16,7 @@ public: void Test() { static int i = 0; // ֲ̬, ֻᱻʼһ - ++i; + ++i; // ʽֵڱiֵ if (i > 100) { return; @@ -29,7 +29,7 @@ public: // para1: www.baidu.com/; para2: callback this->Get(reqBuff, [this](HttpClientC* pHttpClient){ // lambdaʽΪʵ - if (pHttpClient != nullptr) { // httpclientȷյӦϢ + if (nullptr != pHttpClient) { // httpclientȷյӦϢ CELLLog_Info("[httpclient][Test] recv http web server msg [bodyLen = %s] [id = %d].", pHttpClient->HeaderGetStr("Content-Length", "?"), i); CELLLog_Info("[httpclient][Test] recv http web server msg [content = %s] [id = %d].", pHttpClient->Content(), i); @@ -47,7 +47,7 @@ public: sprintf(reqBuff, "http://192.168.56.101:4568/sub?a=%d&b=1", i); this->Get(reqBuff, [this](HttpClientC* pHttpClient){ // lambdaʽΪʵ - if (pHttpClient != nullptr) { // httpclientȷյӦϢ + if (nullptr != pHttpClient) { // httpclientȷյӦϢ CELLLog_Info("[httpclient][Test] recv http web server msg [bodyLen = %s] [id = %d].", pHttpClient->HeaderGetStr("Content-Length", "?"), i); CELLLog_Info("[httpclient][Test] recv http web server msg [content = %s] [id = %d].", pHttpClient->Content(), i); @@ -65,7 +65,7 @@ public: this->Post("http://192.168.56.101:4568/jsonTest", reqBuff, [this](HttpClientC* pHttpClient){ // lambdaʽΪʵ - if (pHttpClient != nullptr) { // httpclientȷյӦϢ + if (nullptr != pHttpClient) { // httpclientȷյӦϢ CELLLog_Info("[httpclient][Test] recv http web server json msg2 to way2: [bodyLen = %s] [id = %d].", pHttpClient->HeaderGetStr("Content-Length", "?"), i); CELLLog_Info("[httpclient][Test] recv http web server json msg2 to way2: [content = %s] [id = %d].", pHttpClient->Content(), i); @@ -85,7 +85,7 @@ public: }; -int main(int argc, char* args[]) +int main(int argc, char* args[]) // [2024-6-22] { // windowϵͳ-̨ӡ֧UTF-8ʽַ #if _WIN32 && _CONSOLE @@ -119,7 +119,7 @@ int main(int argc, char* args[]) } CELLLog_Info("[httpclient] recv http web server msg1: \n"); - // BUGڿָʷ + // BUGڿָʷ-ѽָп auto responseStr = pHttpClient->Content(); CELLLog_Info("[Content=%s]\n", responseStr); }); // ȡIPб diff --git a/engine2.0/engine2.0/HelloHttp/Server.cpp b/engine2.0/engine2.0/HelloHttp/Server.cpp index f0feb74de5dcb2b5e0275de0e61b8dc2b9344ee6..f7c8b3a2c507c9f7b6f3775b2dfcb76af179ac42 100644 --- a/engine2.0/engine2.0/HelloHttp/Server.cpp +++ b/engine2.0/engine2.0/HelloHttp/Server.cpp @@ -1,6 +1,6 @@ // 分析:当前工程是httpserver(简易的web服务器) #pragma execution_character_set("utf-8") - +// [2024-6-30-ok] #include "TcpHttpServer.hpp" #include "Log.hpp" #include "Config.hpp" @@ -16,7 +16,7 @@ public: virtual void OnNetMsg(Server* pServer, Client* pClient, netmsg_DataHeader* header) { // 收到消息 - HttpClientS* pHttpClient = dynamic_cast(pClient); // 将父类指针变量强转为子类指针变量 + HttpClientS* pHttpClient = dynamic_cast(pClient); // 将父类指针变量强转为子类指针变量[确保此时父类指针装的是被强转的子类指针对象,否则可能出现访问属性或方法的错误] if (nullptr == pHttpClient) { CELLLog_Error("nullptr == pHttpClient"); return; @@ -38,7 +38,7 @@ public: int b = pHttpClient->ArgsGetInt("b", 0); int c = a + b; - char respBodyBuff[32] = {0}; + char respBodyBuff[32] = {0}; // 编程规范:变量在使用前都应该初始化 sprintf(respBodyBuff, "a + b = %d", c); pHttpClient->Resp200OK(respBodyBuff, strlen(respBodyBuff)); @@ -103,7 +103,7 @@ public: } FILE* file = fopen(filePath.c_str(), "rb"); // para2-二进制格式读取文件,采用c风格读取文件 - if (file == nullptr) { + if (nullptr == file) { return false; } @@ -122,7 +122,7 @@ public: // 分析:推荐读取的文件不能太大,发送缓冲区很小,超过之后,目前也发不出去, // 大文件的发送,后面会补充进来。 // 根据当前读取文件大小申请堆内存,存储文件内容缓存区buff - char* buff = new char[bytesize]; + char* buff = new char[bytesize]; // 数组指针,本质是一个指针,但这个指针指向了一个数组 auto readsize = fread(buff, 1, bytesize, file); // 读取的是二进制数据形式-rb if (readsize != bytesize) { CELLLog_Warring("readsize != bytesize, [url = %s]", filePath.c_str()); @@ -141,13 +141,13 @@ public: } // - void SetWwwRoot(const char* wwwRoot) + void SetWwwRoot(char const* wwwRoot) { _wwwRoot = wwwRoot; } // - void SetIndexPage(const char* indexPage) + void SetIndexPage(char const* indexPage) { _indexPage = indexPage; } diff --git a/engine2.0/engine2.0/WebSocketServer/ServerLog.txt b/engine2.0/engine2.0/WebSocketServer/ServerLog.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/engine2.0/engine2.0/WebSocketServer/WebSocketServer.vcxproj b/engine2.0/engine2.0/WebSocketServer/WebSocketServer.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..8184440c175bc60e7ac4f008112e71347eb0499d --- /dev/null +++ b/engine2.0/engine2.0/WebSocketServer/WebSocketServer.vcxproj @@ -0,0 +1,86 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {2A3173AA-CB78-44E3-A38E-61BC0D5ECCA2} + HelloHttp + + + + Application + true + v120 + MultiByte + + + Application + false + v120 + true + MultiByte + + + + + + + + + + + + + $(SolutionDir)../bin/$(Configuration)\ + $(SolutionDir)../tmp/$(Configuration)\ + + + $(SolutionDir)../bin/$(Configuration)\ + $(SolutionDir)../tmp/$(Configuration)\ + + + + Level3 + Disabled + false + ..\Depends\include + + + true + + + + + Level3 + MaxSpeed + true + true + false + + + true + true + true + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/engine2.0/engine2.0/WebSocketServer/WebSocketServer.vcxproj.filters b/engine2.0/engine2.0/WebSocketServer/WebSocketServer.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..6996947d20c33c9a569e2852077037cc6f6d044f --- /dev/null +++ b/engine2.0/engine2.0/WebSocketServer/WebSocketServer.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + + + 源文件 + + + \ No newline at end of file diff --git a/engine2.0/engine2.0/WebSocketServer/WebSocketServer.vcxproj.user b/engine2.0/engine2.0/WebSocketServer/WebSocketServer.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..ef5ff2a1fae669e995b58fb11281de92ca5fab27 --- /dev/null +++ b/engine2.0/engine2.0/WebSocketServer/WebSocketServer.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/engine2.0/engine2.0/WebSocketServer/config/HelloHttp.exe b/engine2.0/engine2.0/WebSocketServer/config/HelloHttp.exe new file mode 100644 index 0000000000000000000000000000000000000000..d9974df747beb4b71baa9cafffc0b658352386a6 Binary files /dev/null and b/engine2.0/engine2.0/WebSocketServer/config/HelloHttp.exe differ diff --git a/engine2.0/engine2.0/WebSocketServer/config/WebEasyServer_wins_ipv4.bat b/engine2.0/engine2.0/WebSocketServer/config/WebEasyServer_wins_ipv4.bat new file mode 100644 index 0000000000000000000000000000000000000000..f72be81bd3efa837dbb0be5dbc744cc23fa2ef61 --- /dev/null +++ b/engine2.0/engine2.0/WebSocketServer/config/WebEasyServer_wins_ipv4.bat @@ -0,0 +1,37 @@ + +@echo off +:::::::::::::::::: +::key-val +::ֵ +::std::map + +:::::::::::::::::: +::IPַ +set cmd="strIP=any" +::˶˿ +set cmd=%cmd% nPort=4568 +::Ϣ߳ +set cmd=%cmd% nThread=1 +::ͻ +set cmd=%cmd% nMaxClient=100064 +::ͻ˷ͻСֽڣ +set cmd=%cmd% nSendBuffSize=20480 +::ͻ˽ջСֽڣ +set cmd=%cmd% nRecvBuffSize=20480 +:: յϢ󽫷ӦϢ +set cmd=%cmd% -sendback +::ʾͻд +::sendfullʾʱʾϢ +set cmd=%cmd% -sendfull +::յĿͻϢIDǷ +set cmd=%cmd% -checkMsgID +::Զ־ δʹ +set cmd=%cmd% -p +:: webӦҳĬrootĿ¼Ĭҳ +set cmd=%cmd% wwwroot=D:/c++code/engine2.0о/engine2.0/engine2.0/engine2.0/HelloHttp/www +set cmd=%cmd% indexpage=index.html + +:: +HelloHttp %cmd% + +pause diff --git a/engine2.0/engine2.0/WebSocketServer/server.cpp b/engine2.0/engine2.0/WebSocketServer/server.cpp new file mode 100644 index 0000000000000000000000000000000000000000..81ff9dc12204ab851c70cc7e2753f44e64d18ee8 --- /dev/null +++ b/engine2.0/engine2.0/WebSocketServer/server.cpp @@ -0,0 +1,143 @@ +// 分析:当前工程是websocket服务端(简易的web服务器) +#pragma execution_character_set("utf-8") + +#include "TcpHttpServer.hpp" +#include "Log.hpp" +#include "Config.hpp" +#include "sha1.hpp" +#include "base64.hpp" + + +using namespace doyou::io; // 命名空间 + + +class MyServer : public TcpHttpServer +{ +public: + // 处理网路消息 + virtual void OnNetMsg(Server* pServer, Client* pClient, netmsg_DataHeader* header) + { + // 收到消息 + HttpClientS* pHttpClient = dynamic_cast(pClient); // 将父类指针变量强转为子类指针变量[确保此时父类指针装的是被强转的子类指针对象,否则可能出现访问属性或方法的错误] + if (nullptr == pHttpClient) { + CELLLog_Error("nullptr == pHttpClient"); + return; + } + + // 解析消息 + if (!pHttpClient->GetRequestInfo()) { + CELLLog_Error("get http req info err."); + return; + } + + auto strUpgrade = pHttpClient->HeaderGetStr("Upgrade", ""); + if (0 != strcmp(strUpgrade, "websocket")) { + CELLLog_Error("not found Upgrade: websocket"); + return; + } + + auto cKey = pHttpClient->HeaderGetStr("Sec-WebSocket-Key", nullptr); // 客户端key + if (nullptr == cKey) { + CELLLog_Error("not fount Sec-WebSocket-Key"); + return; + } + + std::string sKey = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // 服务端固定key + sKey = cKey + sKey; + + unsigned char p[20]; + SHA1_String((const unsigned char*)sKey.c_str(), sKey.length(), p); + + + + + + + + } + + +private: + + +}; + + +int main(int argc, char* args[]) +{ + // 设置运行日志名称 + Log::Instance().setLogPath("ServerLog", "w", false); + Config::Instance().Init(argc, args); + + // 解析配置 + const char* strIP = Config::Instance().getStr("strIP", "any"); + uint16_t nPort = Config::Instance().getInt("nPort", 4568); + int nThread = Config::Instance().getInt("nThread", 1); + + if (strcmp(strIP, "any") == 0) + { + strIP = nullptr; + } + + MyServer server; // 在栈空间实例化对象 + if (Config::Instance().hasKey("-ipv6")) { + CELLLog_Info("-ipv6"); + server.InitSocket(AF_INET6); + } + else { + + CELLLog_Info("-ipv4"); + server.InitSocket(); + } + + // 解析http配置 + // 分析:调试模式读取不到配置文件配置信息, 就采用默认值 + const char* wwwroot = Config::Instance().getStr("wwwroot", "./www"); + const char* indexpage = Config::Instance().getStr("indexpage", "index.html"); + server.SetWwwRoot(wwwroot); + server.SetIndexPage(indexpage); + + server.Bind(strIP, nPort); + // 分析:服务器同一时刻能监听的最大客户端数量,可以提高服务器连接客户端的效率 + server.Listen(SOMAXCONN); // 64 + server.Start(nThread); + + // 在主线程中等待用户输入命令 + while (true) + { + char cmdBuf[256] = {}; + scanf("%s", cmdBuf); // 等待用户输入,当前函数为阻塞函数 + if (0 == strcmp(cmdBuf, "exit")) + { + server.Close(); + break; + } + else { + CELLLog_Info("undefine cmd"); + } + } + + CELLLog_Info("exit."); + + + + return 0; +} + + +/* +// html脚本字符串, c/c++中逻辑换行符[\]: 当前行和下面一行逻辑合并为同一行 +char htmlStr[] = +"\ +\ +\ +\ + hello web\ +\ +\ + \ + \ +\ +\ +"; +*/ diff --git a/engine2.0/engine2.0/WebSocketServer/www/big.docx b/engine2.0/engine2.0/WebSocketServer/www/big.docx new file mode 100644 index 0000000000000000000000000000000000000000..a10c5be7c99c318e9e2945efcecf8a0bad16ec04 Binary files /dev/null and b/engine2.0/engine2.0/WebSocketServer/www/big.docx differ diff --git a/engine2.0/engine2.0/WebSocketServer/www/html_test.bak.html b/engine2.0/engine2.0/WebSocketServer/www/html_test.bak.html new file mode 100644 index 0000000000000000000000000000000000000000..eec366da1f4c84e5b9235a010cd313b4a79907c1 --- /dev/null +++ b/engine2.0/engine2.0/WebSocketServer/www/html_test.bak.html @@ -0,0 +1,10 @@ + + + + hello web + + + + + + \ No newline at end of file diff --git a/engine2.0/engine2.0/WebSocketServer/www/websocket_test.html b/engine2.0/engine2.0/WebSocketServer/www/websocket_test.html new file mode 100644 index 0000000000000000000000000000000000000000..edbf63fed0152097583f288582e51752b7fcbbe1 --- /dev/null +++ b/engine2.0/engine2.0/WebSocketServer/www/websocket_test.html @@ -0,0 +1,47 @@ + + + + websocket-client + + + + + + + + + + \ No newline at end of file diff --git a/engine2.0/engine2.0/engine1.0/engine1.0.vcxproj b/engine2.0/engine2.0/engine1.0/engine1.0.vcxproj index 9864351e0878880fa16896f03d9eb75265454e92..4bc9e30c380f8d37a2ca4883b16e7974ae60932b 100644 --- a/engine2.0/engine2.0/engine1.0/engine1.0.vcxproj +++ b/engine2.0/engine2.0/engine1.0/engine1.0.vcxproj @@ -67,6 +67,7 @@ + @@ -78,6 +79,7 @@ + diff --git a/engine2.0/engine2.0/engine1.0/engine1.0.vcxproj.filters b/engine2.0/engine2.0/engine1.0/engine1.0.vcxproj.filters index ff52ea5bb7fadb7546a1f239d773a0b43dc2f8e8..9d73460a9c692615fe1e0c3ccadecab17437eb35 100644 --- a/engine2.0/engine2.0/engine1.0/engine1.0.vcxproj.filters +++ b/engine2.0/engine2.0/engine1.0/engine1.0.vcxproj.filters @@ -13,6 +13,9 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {f15de6e4-01cb-4591-8f34-5a2b4bbd3db6} + @@ -126,5 +129,11 @@ 源文件 + + third + + + third + \ No newline at end of file diff --git a/engine2.0/engine2.0/engine2.0.sdf b/engine2.0/engine2.0/engine2.0.sdf index d64525ef18fa41b232fadfc7b9ea2bf1d79b67c5..9a295f8992037e95d6cc600e7318ef4fb03daca1 100644 Binary files a/engine2.0/engine2.0/engine2.0.sdf and b/engine2.0/engine2.0/engine2.0.sdf differ diff --git a/engine2.0/engine2.0/engine2.0.sln b/engine2.0/engine2.0/engine2.0.sln index 2be673dc310bb388a66f55f1ba30e485ccb73024..775508a469834e7fbaadd8bfaa79c98fedf264ff 100644 --- a/engine2.0/engine2.0/engine2.0.sln +++ b/engine2.0/engine2.0/engine2.0.sln @@ -24,6 +24,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EasyHttpClient", "EasyHttpC EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenAI", "OpenAI\OpenAI.vcxproj", "{2512751B-C22A-4E16-84B8-8B94CDA63114}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WebSocketServer", "WebSocketServer\WebSocketServer.vcxproj", "{2A3173AA-CB78-44E3-A38E-61BC0D5ECCA2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -62,6 +64,10 @@ Global {2512751B-C22A-4E16-84B8-8B94CDA63114}.Debug|Win32.Build.0 = Debug|Win32 {2512751B-C22A-4E16-84B8-8B94CDA63114}.Release|Win32.ActiveCfg = Release|Win32 {2512751B-C22A-4E16-84B8-8B94CDA63114}.Release|Win32.Build.0 = Release|Win32 + {2A3173AA-CB78-44E3-A38E-61BC0D5ECCA2}.Debug|Win32.ActiveCfg = Debug|Win32 + {2A3173AA-CB78-44E3-A38E-61BC0D5ECCA2}.Debug|Win32.Build.0 = Debug|Win32 + {2A3173AA-CB78-44E3-A38E-61BC0D5ECCA2}.Release|Win32.ActiveCfg = Release|Win32 + {2A3173AA-CB78-44E3-A38E-61BC0D5ECCA2}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/engine2.0/engine2.0/engine2.0.v12.suo b/engine2.0/engine2.0/engine2.0.v12.suo index 963110dded4533b29d363ac4bc27342b83d11a87..99f966ed438c1ab92faed732d153c5b8a1f21ea8 100644 Binary files a/engine2.0/engine2.0/engine2.0.v12.suo and b/engine2.0/engine2.0/engine2.0.v12.suo differ