# anet **Repository Path**: lee-gitpro/anet ## Basic Information - **Project Name**: anet - **Description**: anet是c++实现游戏服务器框架,内含log, timer, http, tcp,pool等组件。其中log支持同步和异步模式;timer是时间轮实现的高效定时器;tcp是基于asio实现的异步网络,同时实现了tcp server和tcp client;http是在tcp模块基础上实现的http server和http client,其中http client支持同步方式;pool实现了对象池。 - **Primary Language**: C++ - **License**: Not specified - **Default Branch**: master - **Homepage**: https://gitee.com/gavingqf - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 6 - **Created**: 2025-04-18 - **Last Updated**: 2025-04-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # summary The anet libraries are server modules which support tcp/http with server and client mode, log, timer, pool module and so on. # detail modules description - tcp module The tcp module supports tcp net with ASIO(BOOT.ASIO) for asynchronous and synchronous mode. For server and client mode, we should declare a session derived from ISession and declare a session factory derived from ISessionFactory. please see the following examples showing how to use them. The tcp client example: ```c++ #include #include "all.hpp" // tcp client header. #include "log.h" #include "default_interface.hpp" // define sleep ms. #define sleepMS(x) std::this_thread::sleep_for(std::chrono::milliseconds(x)) void main() { anet::tcp::Client client(2); client.setPacketParser(new anet::tcp::CBigCodec()); for (;;) { auto session = new anet::tcp::CSession(); client.setSession(session); while (client.syncConnect("10.24.11.20", 5566)) { break; } session->sendMsg(1, "hello"); session->close(); sleepMS(10); } } ``` The tcp client for synchronous mode ```c++ #include "all.hpp" // tcp client header. #include "log.h" #include "default_interface.hpp" void main() { anet::tcp::Client client(2); client.setPacketParser(new anet::tcp::CBigCodec()); // Synchronous session. auto session = new anet::tcp::CSyncSession(); client.setSession(session); if (!client.syncConnect("127.0.0.1", 5566)) { return -1; } // send message asynchronously. long long id = 0; auto send = [session,&id]() { std::string strIndex = std::to_string(id++); auto msgId = 1; auto &&msg = strIndex; session->Send(msgId, msg); }; // thread and its execution body. std::thread th([session]() { long long id = 0; for (;;) { // require message from server synchronously. std::string strIndex = std::to_string(id++); auto res = session->require(1, strIndex); Ainfo("{}:{}",res.msgId, res.message.c_str()); // sleepMS(1); } }); th.detach(); // main thread to do it. for (;;) { send(); sleepMS(1); } } ``` The tcp server example: ```c++ // first declare CClientSession defined as followings: #include #include "share_ptr_session.hpp" #include "log.h" // get thread id. inline unsigned int getThreadId() { std::thread::id this_id = std::this_thread::get_id(); return *(unsigned int*)&this_id; } class CClientSession; using SharePtrSession = anet::tcp::CSharePtrSession; class CClientSession { public: CClientSession() = default; virtual ~CClientSession() = default; public: // on message callback. void OnMessage(const char *msg, int len) { const char *content = msg + gProto_head_size; auto msgId = ntohs(*(uint16*)(content)); Adebug("msg id:{},msg:{},thread id:{}", msgId, content + sizeof(uint16), getThreadId()); m_pSession->Send(msg, len); } // on tcp connection connected. void OnConnected() { Adebug("{} {}, thread id:{}", m_pSession->getRemoteIP(), "connected in", getThreadId()); } // on tcp connection terminate. void OnTerminate() { Adebug("{} {}, thread id:{}", m_pSession->getRemoteIP(), "disconnected in", getThreadId()); } void SetSession(SharePtrSession *pSession) { m_pSession = pSession; } private: // session pointer. SharePtrSession *m_pSession; }; // end of the client session declaration. // main function as following: #include #include "all.hpp" // tcp server header. #include "log.h" #include "default_interface.hpp" // define sleep ms. #define sleepMS(x) std::this_thread::sleep_for(std::chrono::milliseconds(x)) void main() { // tcp server. // anet::tcp::CEventLoop loop(2); // anet::tcp::CServer server(loop); anet::tcp::Server server(3); server.proxy().setPacketParser(new anet::tcp::CBigCodec()); // server.proxy().setSessionFactory(new anet::tcp::CSessionFactory()); using userSessionType = anet::tcp::CSharePtrSession; using userSessionFactoryType = anet::tcp::CSharePtrSessionFactory; auto sessionFactory = new userSessionFactoryType(); server.proxy().setSessionFactory(sessionFactory); if (!server.proxy().start("0", 5566)) { return -1; } // main thread run. bool busy = false; int runCount = 1000000; for (;;) { busy = false; // tcp net run. if (CMainService::instance().run(runCount)) { busy = true; } // timer run. STimeWheelSpace::CTimeWheel::instance().run(); if (!busy) { sleepMS(1); } } } ``` - http module The http module is wrapped from tcp module for POST/GET method. The http client example: ```c++ #include #include "all.hpp" // http client header. #include "log.h" // define sleepMS. #define sleepMS(x) std::this_thread::sleep_for(std::chrono::milliseconds(x)) void main() { // http client test. // http synchronous session factory. auto sessionFactory = new anet::http::httSyncSessionFactory; int gSize = 10; for (int i = 0; i < gSize; i++) { auto thrd = std::make_unique([sessionFactory]() { anet::http::CHttpSyncClient client(sessionFactory); for (;;) { // get requirement auto getRet = client.get("10.24.11.20:8335", "/anet", ""); AInfo("status:%d,content:%s", getRet.first, getRet.second.c_str()); // post requirement auto postRet = client.post("10.24.11.20:8335", "/anet", ""); AInfo("status:%d,content:%s", postRet.first, postRet.second.c_str()); // sleepMS(1); } }); thrd->detach(); } for (;;) { sleepMS(1000); } // just for the code's rightness. delete sessionFactory; ``` The http server example: ```c++ #include #include "all.hpp" // http server header. #include "log.h" // define sleepMS. #define sleepMS(x) std::this_thread::sleep_for(std::chrono::milliseconds(x)) void main() { anet::http::CHttpServer server(2); // == define all kinds of post interfaces. server.post("/anet", [](const anet::http::HttpRes& res) ->anet::http::httpResPair { return { anet::http::httpStatus::OK, std::move(std::string("hello,post anet")) }; }); server.get("/anet", [](const anet::http::HttpRes& res) ->anet::http::httpResPair { return { anet::http::httpStatus::OK, std::move(std::string("hello,get anet")) }; }); server.start("0", 8335); // wait for exit for (;;) { sleepMS(1); } } ``` - log module The log module supports asynchronous and synchronous mode. And the code is in the log fold. The log example: ```c++ #include "log.h" // log header. #include // define sleepMS. #define sleepMS(x) std::this_thread::sleep_for(std::chrono::milliseconds(x)) void main() { // init log module anet::log::initLog("./log", "test-net", anet::log::eLogLevel::debug, 1000); // set log level. if (argc >= 2) { anet::log::setLogLevel(anet::log::eLogLevel(atoi(argv[1]))); } else { anet::log::setLogLevel(anet::log::eLogLevel::debug); } // log out synchronously with {} flag. Adebug("{}", "=== start ==="); // log out synchronously with {} flag. debug("{}", "=== start ==="); // log out synchronously with traditional(%d,%s) flag. Debug("%s", "=== end ===") // log out synchronously with traditional(%d,%s) flag. ADebug("%s", "=== end ===") for (;;) { sleepMS(1); } } ``` - timer module The timer module is wrapped from the time wheel algorithm. And the code is in the timer fold. The timer example: ```c++ #include #include #include "time_wheel.h" // timer header. // define sleepMS. #define sleepMS(x) std::this_thread::sleep_for(std::chrono::microseconds(x)) void main() { // create timer register. STimeWheelSpace::CTimerRegister timer; // add 0 once timer(10s). timer.add_once_timer([](void*) { printf("0 timer out"); }, 0, 10 * 1000); // add 1 repeated timer(1s). timer.add_repeated_timer([&timer](void*) { printf("1 timer out"); // kill the 1 timer. timer.kill_timer(1); }, 1, 1000); // run variadic template function after 1s. m_register.add_var_once_timer(0, 1000, [](std::string a, int b, int c) { Adebug("a:{},b:{},c:{}", a, b, c); }, "1", 2, 3); // run the timer to execute the events. for (;;) { STimeWheelSpace::CTimeWheel::instance().run(); sleepMS(10); } } ``` - pool module The pool module supports class pool and memory buckets. And the code is in the pool fold. # how to use Install cmake, and compile this module(CMakeLists.txt) to STATIC or SHARED library. # note - All the modules run well in vc-studio2017 and Linux g++(7.5.0)version. And the compiler must support c++17 for std::apply and std::any. - The tcp server for the upper single thread can reach 40W QPS at 8CPU and 16G memory of Linux. And the QPS can reach 80W if the tcp server using multiple thread for the upper logic. (服务器上层使用单线程模式,8核16G的i7Linux上,50W+的QPS;如果上层是多线程模式,在上述环境能达到80W+的QPS)。 - If you want to compile the anet module in windows, you can open the anet with vscode, and it will produce build fold including anet.sln. then you can open it with vc-studio2017. (如果你想用windows的vc-studio2017打开这个库,你只需要用vscode打开这个库,然后vscode会自动帮你生成build目录,里面包含anet.sln)。