吊床厂家
免费服务热线

Free service

hotline

010-00000000
吊床厂家
热门搜索:
成功案例
当前位置:首页 > 成功案例

看一看:一个开源的服务器框架,特别适用于开发小游戏

发布时间:2022-03-31 16:23:13 阅读: 来源:吊床厂家
一个开源的服务器框架,特别适用于开发小游戏 作者:佚名 2021-03-08 10:21:22 开发 前端 一个跨平台的c++<->lua服务器快速解决方案,该框架即可快速响应服务器开发工作,设计思想:“让事情变得更简单”

jwEngine

一个跨平台的c++<->lua服务器快速解决方案,该框架即可快速响应服务器开发工作,设计思想:,让事情变得更简单

网络底层采用libuv(node.js底层库),异步io助力使单线程也能释放澎湃动力,跨平台支持epoll、iocp、ipv6。框架支持tcp、udp/kcp、websocket、http,并保证了接口的一致性,使用了sol2将所有接口都导出到lua,可以选择用lua开发逻辑。

使用modern c++开发,尽可能的使用std::move、std::string_view减少内存复制。

该框架使用异步事件,不建议使用多线程,避免多线程上下文切换开销和破坏代码美感,网络部分和逻辑部分使用一个主事件循环驱动。建议的方案是多进程单线程的横向扩展,按照业务控制各个进程的粒度,当然mysql和redis可以加入到线程池中。

创建一个tcp服务器

只需要简单几行代码即可创建一个tcp高性能服务器,并自动处理数据包头和粘包(其中包头包含消息长度和协议号),构建一个完好的NetPacket交给你。

  1. classINetEvent:publicNetEvent
  2. {
  3. public:
  4. virtualvoidonAccept(NetConnect*conn){}
  5. virtualvoidonClose(NetConnect*conn){}
  6. virtualvoidonMsg(NetConnect*conn,intmsgtype,NetPacket*pack){}
  7. };
  8. intmain()
  9. {
  10. EventLoop::Instance()->init();
  11. INetEventeve;
  12. NetServerserver(EventLoop::Instance(),&eve);
  13. server房子强拆可以报警吗.listen("127.0.0.1",3001);
  14. returnEventLoop::Instance()->run();
  15. }
创建一个kcp服务器

c++的kcp服务器示例,快速构建你的帧同步服务器,保证消息的可靠性

  1. classKNetEvent:publicKcpEvent
  2. {
  3. public:
  4. virtualvoidonAccept(KcpSession*conn){};
  5. virtualvoidonClose(KcpSession*conn){};
  6. virtualvoidonMsg(KcpSession*conn,intmsgtype,UdpPacket*pack){}
  7. virtualvoidonUdpTimeout(KcpSession*s){}
  8. };
  9. intmain()
  10. {
  11. EventLoop::Instance()->init();
  12. KNetEventeve;
  13. KcpServerserver(EventLoop::Instance(),&eve);
  14. server.start("127.0.0.1",3001);
  15. returnEventLoop::Instance()->run();
  16. }
创建一个websocket服务器

自动完成解析websocket协议工作

  1. classIWebEvent:publicWebSocketEvent
  2. {
  3. public:
  4. virtualvoidonHandshake(WebSocketConnect*conn){};
  5. virtualvoidonAccept(WebSocketConnect*conn){};
  6. virtualvoidonClose(WebSocketConnect*conn){};
  7. virtualvoidonMsg(WebSocketConnect*conn,WebSocketPacket*pack){};
  8. };
  9. intmain()
  10. {
  11. EventLoop::Instance()->init();
  12. IWebEventwevent;
  13. WebSocketServerserver(EventLoop::Instance(),&wevent);
  14. server.listen("127.0.0.1",8080);
  15. returnEventLoop::Instance()->run();
  16. }
创建一个http服务器

http仅支持简单的get post请求

  1. constchar*html=R"(<html>
  2. <body>
  3. <h1>login</h1>
  4. <p>helloworld!</p>
  5. <formaction="login"method="post">
  6. <inputtype="text"name="user"/>
  7. <inputtype="password"name="pass"/>
  8. <inputtype="submit"value="login"/>
  9. </form>
  10. </body>
  11. </html>)";
  12. constchar*succeed=""
  13. "<html>"
  14. "<body>"
  15. "<h1>loginsucceed</h1>"
  16. "</body>"
  17. "</html>";
  18. constchar*failing=""
  19. "<html>"
  20. "<body>"
  21. "<h1>loginfailing</h1>"
  22. "</body>"
  23. "</html>";
  24. intmain()
  25. {
  26. EventLoop::Instance()->init();
  27. HttpServerserver(EventLoop::Instance());
  28. server.listen("127.0.0.1",80);
  29. server.addGet("/",[](HttpConnect*conn,std::string_view&data){
  30. conn->autoMsg(html);
  31. });
  32. server.addPost("/login",[](HttpConnect*conn,std::string_view&data){
  33. HttpParamhp(data);
  34. if(hp.getStr("user")=="jw"&&hp.getStr("pass")=="1111")
  35. {
  36. conn->autoMsg(succeed);
  37. }
  38. else
  39. {
  40. conn->autoMsg(failing);
  41. }
  42. });
  43. returnEventLoop::Instance()->run();
  44. }
mysql和线程池

这次我们用lua示例:

  1. localconfig=DBConfig:new()
  2. config.device="mysql"
  3. config.ip="127.0.0.1"
  4. config.dbname="jw_test"
  5. config.user="root"
  6. config.pswd="1111"
  7. config.port=3306
  8. pool=DBThreadPool:new(config)
  9. pool:create(1)
  10. func=function(err,result)
  11. while(result:fetch())
  12. do
  13. localid=result:getInt32()
  14. localnum=result:getInt32()
  15. localname=result:getString()
  16. localstr="id:"..id..",num:"..num..",name:"..name
  17. print(str)
  18. end
  19. end
  20. functionexec()
  21. localsql=SqlCommand:new("select*fromtestwhereid=?")
  22. sql:pushInt32(1)
  23. sql:addToPool(pool,func)
  24. end
  25. event_init()
  26. exec()
  27. timer=UTimer:new()
  28. timer:start(function()
  29. pool:update()
  30. end,10,10)
  31. event_run()
任意扩展进程节点

你可以任意扩展你的进程,示例:

base进程 cell进程 db进程 start engine.exe base.lua start engine.exe cell.lua start engine.exe db拆迁不给钱怎么回事.lua 提供一个serialization序列化工具

类似于c++的语法,写起来非常简单,示例:

  1. structtestmsg
  2. {
  3. int32x
  4. int32y
  5. int32z
  6. int8state
  7. vector<int32>vec
  8. read{
  9. [x,y,z,state]
  10. if(state==1)
  11. {
  12. [vec]
  13. }
  14. }
  15. write{
  16. [x,y,z,state,vec]
  17. }
  18. }

通过serialization工具可以将协议的描述文件生成c++和lua代码,自动生成read()和write()的函数实现,使得数据结构快速映射到SocketBuffer中。

目前serialization序列化工具为实验性,可能是脆弱的,建议使用更强大的protobuf。该项目已集成lua-protobuf,使得c++和lua之间的协议无缝衔接。

lua-protobuf的开源地址:lua-protobuf

这个示例展示了c++客户端和lua服务器之间的通讯:快速搭建服务器Demo

构建

你需要一个modern c++17编译器

  • vs2017 测试通过
  • gcc version 9.3.0 测试通过