异步网络消息处理框架
最近一段时间将原来写的kendynet网络框架重写了大部分的代码,让提供的接口更清晰,对用户更友好。
整个框架的架构分层3层:
1)单线程,基于原始数据流的网络接口,在这一层上,没有提供封包的处理,定时器事件等等。使用者可以在此之上按自己的需求做进一步的封装。
2)单线程,提供connection,封包处理,接收发送超时处理。
3)网络逻辑分离的异步网络框架,抽象出三个主要的类型:asynnet_t,sock_ident和msgdisp_t.
asynnet_t:网络处理引擎,使用者创建实例的时候可以传入pollercount参数,其中每一个poller都会在单独的线程中运行.
sock_ident:逻辑层操作的套接口封装,可以安全的在多线程环境下使用.
msgdisp_t:消息分离器,每个分离器有一个对应的消息队列用于接收从网络线程传递过来的消息.
msgdisp_t提供了两种使用模式:
第一种:典型的线程池模式。在这种模式下,可以创建一个消息分离器,多个逻辑线程对这个消息分离器调用
msg_loop.
第二种:共用网络层模式。在一个进程中启动N个线程,每个线程运行一个不同服务,所有这些服务共用网络通信层.
在这种情况下,网络消息需要路由到正确的服务那里.可以每个线程都创建一个消息分离器,各线程在自己的消息分离器上
调用msg_loop处理只属于自己的消息.
下面是一个异步网络服务器的示例:
#include <stdio.h> #include <stdlib.h> #include "core/msgdisp.h" #include "testcommon.h" uint32_t recvsize = 0; uint32_t recvcount = 0; ///int32_t asynnet_bind(msgdisp_t disp,sock_ident sock,void *ud,int8_t raw,uint32_t send_timeout,uint32_t recv_timeout) void asynconnect(msgdisp_t disp,sock_ident sock,const char *ip,int32_t port) { printf("asynconnect\n"); disp->bind(disp,sock,1,0,30*1000); } void asynconnected(msgdisp_t disp,sock_ident sock,const char *ip,int32_t port) { printf("asynconnected\n"); ++client_count; } void asyndisconnected(msgdisp_t disp,sock_ident sock,const char *ip,int32_t port,uint32_t err) { --client_count; } int32_t asynprocesspacket(msgdisp_t disp,sock_ident sock,rpacket_t rpk) { recvsize += rpk_len(rpk); recvcount++; asyn_send(sock,wpk_create_by_other((struct packet*)rpk)); return 1; } void asynconnectfailed(msgdisp_t disp,const char *ip,int32_t port,uint32_t reason) { } int main(int argc,char **argv) { setup_signal_handler(); InitNetSystem(); asynnet_t asynet = asynnet_new(1); msgdisp_t disp = new_msgdisp(asynet, asynconnect, asynconnected, asyndisconnected, asynprocesspacket, asynconnectfailed); int32_t err = 0; disp->listen(disp,argv[1],atoi(argv[2]),&err); uint32_t tick,now; tick = now = GetSystemMs(); while(!stop){ msg_loop(disp,50); now = GetSystemMs(); if(now - tick > 1000) { uint32_t elapse = now-tick; recvsize = (recvsize/elapse)/1000; printf("client_count:%d,recvsize:%d,recvcount:%d\n",client_count,recvsize,recvcount); tick = now; packet_send_count = 0; recvcount = 0; recvsize = 0; } } CleanNetSystem(); return 0; }
项目代码在:https://github.com/sniperHW/luanet
目前只实现了对linux,tcp的网络支持,后续将会先完善这部分代码,并在此之上提供基于user level thread的RPC支持.