一個(gè)開源的服務(wù)器框架,特別適用于開發(fā)小游戲
jwEngine
一個(gè)跨平臺(tái)的c++<->lua服務(wù)器快速解決方案,該框架即可快速響應(yīng)服務(wù)器開發(fā)工作,設(shè)計(jì)思想:“讓事情變得更簡單”
網(wǎng)絡(luò)底層采用libuv(node.js底層庫),異步io助力使單線程也能釋放澎湃動(dòng)力,跨平臺(tái)支持epoll、iocp、ipv6??蚣苤С謙cp、udp/kcp、websocket、http,并保證了接口的一致性,使用了sol2將所有接口都導(dǎo)出到lua,可以選擇用lua開發(fā)邏輯。
使用modern c++開發(fā),盡可能的使用std::move、std::string_view減少內(nèi)存復(fù)制。
該框架使用異步事件,不建議使用多線程,避免多線程上下文切換開銷和破壞代碼美感,網(wǎng)絡(luò)部分和邏輯部分使用一個(gè)主事件循環(huán)驅(qū)動(dòng)。建議的方案是多進(jìn)程單線程的橫向擴(kuò)展,按照業(yè)務(wù)控制各個(gè)進(jìn)程的粒度,當(dāng)然mysql和redis可以加入到線程池中。
創(chuàng)建一個(gè)tcp服務(wù)器
只需要簡單幾行代碼即可創(chuàng)建一個(gè)tcp高性能服務(wù)器,并自動(dòng)處理數(shù)據(jù)包頭和粘包(其中包頭包含消息長度和協(xié)議號(hào)),構(gòu)建一個(gè)完好的NetPacket交給你。
- class INetEvent : public NetEvent
 - {
 - public:
 - virtual void onAccept(NetConnect * conn){}
 - virtual void onClose(NetConnect * conn){}
 - virtual void onMsg(NetConnect * conn, int msgtype, NetPacket * pack){}
 - };
 - int main()
 - {
 - EventLoop::Instance()->init();
 - INetEvent eve;
 - NetServer server(EventLoop::Instance(), &eve);
 - server.listen("127.0.0.1", 3001);
 - return EventLoop::Instance()->run();
 - }
 
創(chuàng)建一個(gè)kcp服務(wù)器
c++的kcp服務(wù)器示例,快速構(gòu)建你的幀同步服務(wù)器,保證消息的可靠性
- class KNetEvent : public KcpEvent
 - {
 - public:
 - virtual void onAccept(KcpSession * conn){};
 - virtual void onClose(KcpSession * conn){};
 - virtual void onMsg(KcpSession * conn, int msgtype, UdpPacket * pack){}
 - virtual void onUdpTimeout(KcpSession * s){}
 - };
 - int main()
 - {
 - EventLoop::Instance()->init();
 - KNetEvent eve;
 - KcpServer server(EventLoop::Instance(), &eve);
 - server.start("127.0.0.1", 3001);
 - return EventLoop::Instance()->run();
 - }
 
創(chuàng)建一個(gè)websocket服務(wù)器
自動(dòng)完成解析websocket協(xié)議工作
- class IWebEvent : public WebSocketEvent
 - {
 - public:
 - virtual void onHandshake(WebSocketConnect * conn){};
 - virtual void onAccept(WebSocketConnect * conn){};
 - virtual void onClose(WebSocketConnect * conn){};
 - virtual void onMsg(WebSocketConnect * conn, WebSocketPacket * pack){};
 - };
 - int main()
 - {
 - EventLoop::Instance()->init();
 - IWebEvent wevent;
 - WebSocketServer server(EventLoop::Instance(), &wevent);
 - server.listen("127.0.0.1", 8080);
 - return EventLoop::Instance()->run();
 - }
 
創(chuàng)建一個(gè)http服務(wù)器
http僅支持簡單的get post請求
- const char * html = R"(<html>
 - <body>
 - <h1>login</h1>
 - <p>hello world!</p>
 - <form action="login" method="post">
 - <input type="text" name="user"/>
 - <input type="password" name="pass"/>
 - <input type="submit" value="login"/>
 - </form>
 - </body>
 - </html>)";
 - const char * succeed = ""
 - "<html>"
 - "<body>"
 - "<h1>login succeed</h1>"
 - "</body>"
 - "</html>";
 - const char * failing = ""
 - "<html>"
 - "<body>"
 - "<h1>login failing</h1>"
 - "</body>"
 - "</html>";
 - int main()
 - {
 - EventLoop::Instance()->init();
 - HttpServer server(EventLoop::Instance());
 - server.listen("127.0.0.1", 80);
 - server.addGet("/", [](HttpConnect *conn, std::string_view & data) {
 - conn->autoMsg(html);
 - });
 - server.addPost("/login", [](HttpConnect *conn, std::string_view & data) {
 - HttpParam hp(data);
 - if (hp.getStr("user") == "jw" && hp.getStr("pass") == "1111")
 - {
 - conn->autoMsg(succeed);
 - }
 - else
 - {
 - conn->autoMsg(failing);
 - }
 - });
 - return EventLoop::Instance()->run();
 - }
 
mysql和線程池
這次我們用lua示例:
- local config = DBConfig:new()
 - config.device = "mysql"
 - config.ip = "127.0.0.1"
 - config.dbname = "jw_test"
 - config.user = "root"
 - config.pswd = "1111"
 - config.port = 3306
 - pool = DBThreadPool:new(config)
 - pool:create(1)
 - func = function(err, result)
 - while(result:fetch())
 - do
 - local id = result:getInt32()
 - local num = result:getInt32()
 - local name = result:getString()
 - local str = "id:" .. id .. ", num:" .. num .. ", name:" .. name
 - print(str)
 - end
 - end
 - function exec()
 - local sql = SqlCommand:new("select * from test where id = ?")
 - sql:pushInt32(1)
 - sql:addToPool(pool, func)
 - end
 - event_init()
 - exec()
 - timer = UTimer:new()
 - timer:start(function ()
 - pool:update()
 - end, 10, 10)
 - event_run()
 
任意擴(kuò)展進(jìn)程節(jié)點(diǎn)
你可以任意擴(kuò)展你的進(jìn)程,示例:
| base進(jìn)程 | cell進(jìn)程 | db進(jìn)程 | 
|---|---|---|
| start engine.exe base.lua | start engine.exe cell.lua | start engine.exe db.lua | 
提供一個(gè)serialization序列化工具
類似于c++的語法,寫起來非常簡單,示例:
- struct testmsg
 - {
 - int32 x
 - int32 y
 - int32 z
 - int8 state
 - vector<int32> vec
 - read{
 - [x, y, z, state]
 - if(state == 1)
 - {
 - [vec]
 - }
 - }
 - write{
 - [x, y, z, state, vec]
 - }
 - }
 
通過serialization工具可以將協(xié)議的描述文件生成c++和lua代碼,自動(dòng)生成read()和write()的函數(shù)實(shí)現(xiàn),使得數(shù)據(jù)結(jié)構(gòu)快速映射到SocketBuffer中。
目前serialization序列化工具為實(shí)驗(yàn)性,可能是脆弱的,建議使用更強(qiáng)大的protobuf。該項(xiàng)目已集成lua-protobuf,使得c++和lua之間的協(xié)議無縫銜接。
lua-protobuf的開源地址: lua-protobuf
這個(gè)示例展示了c++客戶端和lua服務(wù)器之間的通訊: 快速搭建服務(wù)器Demo
構(gòu)建
你需要一個(gè)modern c++17編譯器
- vs2017 測試通過
 - gcc version 9.3.0 測試通過
 















 
 
 






 
 
 
 