2 Star 8 Fork 1

gavingqf / anet

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
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:

  #include <chrono>
  #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

#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:

// first declare CClientSession defined as followings:
#include <functional>
#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<CClientSession>;

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 <chrono>
#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<CClientSession>;
   using userSessionFactoryType = anet::tcp::CSharePtrSessionFactory<userSessionType>;
   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:
   #include <chrono>
   #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<std::thread>([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:

   #include <chrono>
   #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:
   #include "log.h" // log header.
   #include <chrono>
   // 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:

  #include <chrono>
  #include <stdlib.h>
  #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)。

空文件

简介

anet是c++实现游戏服务器框架,内含log, timer, http, tcp,pool等组件。其中log支持同步和异步模式;timer是时间轮实现的高效定时器;tcp是基于asio实现的异步网络,同时实现了tcp server和tcp client;http是在tcp模块基础上实现的http server和http client,其中http client支持同步方式;pool实现了对象池。 展开 收起
C++ 等 3 种语言
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
C++
1
https://gitee.com/gavingqf/anet.git
git@gitee.com:gavingqf/anet.git
gavingqf
anet
anet
master

搜索帮助