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交给你。
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()
{
CommPool::init<NetPacket>(100);
EventLoop::Instance()->init();
INetEvent eve;
NetServer server(EventLoop::Instance(), &eve);
server.listen("127.0.0.1", 3001);
EventLoop::Instance()->Run();
return 0;
}
创建一个kcp服务器
c++的kcp服务器示例,快速构建你的帧同步服务器,保证消息的可靠性
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()
{
CommPool::init<UdpPacket>(10);
EventLoop::Instance()->init();
KNetEvent eve;
KcpServer server(EventLoop::Instance(), &eve);
server.start("127.0.0.1", 3001);
EventLoop::Instance()->Run();
return 0;
}
创建一个websocket服务器
自动完成解析websocket协议工作
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()
{
CommPool::init<WebSocketPacket>(10);
EventLoop::Instance()->init();
IWebEvent wevent;
WebSocketServer server(EventLoop::Instance(), &wevent);
server.listen("127.0.0.1", 8080);
EventLoop::Instance()->Run();
return 0;
}
创建一个http服务器
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()
{
CommPool::init<HttpConnect>(10);
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);
}
});
EventLoop::Instance()->Run();
return 0;
}
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(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()
任意扩展进程节点
你可以任意扩展你的进程,示例:
base进程 | cell进程 | db进程 |
---|---|---|
start engine.exe base.lua | start engine.exe cell.lua | start engine.exe db.lua |
提供一个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工具可以生成c++或者lua代码,自动补全read()和write()函数,使得数据结构快速映射到SocketBuffer中。倘若该工具无法满足你,你也可以非常轻松的接入protobuff。
构建
你需要一个modern c++17编译器
- vs2017 测试通过
- gcc version 9.3.0 测试通过
进一步了解
更多使用示例请参考example. 同时欢迎fork和贡献代码
建议
有任何意见或bug,请联系QQ:754420038