revolver的核心部件库core是基于revolver base之上进行封装的,实现TCP连接管理、消息隐射管理、服务登记和感知 、IFrame框架和插件等。以下是core的模块结构图:
class CCorePacket : public CBasePacket { public: void set_data(CBasePacket& packet, bool zlib = true); void get_data(CBasePacket& packet); ... protected: //编码解码函数 virtual void Pack(BinStream& strm) const; //解码函数 virtual void UnPack(BinStream& strm); ... public: uint32_t server_id_; //服务器ID uint8_t server_type_; //服务器类型,0表示客户端 uint32_t msg_id_; //消息ID uint8_t msg_type_; //消息类型,例如独立的PING PONG消息,握手消息,应用层消息等 string data_; //消息内容 };
typedef enum PacketClass { CORE_HANDSHAKE, //TCP握手协议类型 CORE_REQUEST, //TCP消息载体类型 CORE_PING, //TCP心跳协议类型 CORE_MEDIA_SHELL, CORE_ZLIB, CORE_PONG }PacketClass;
void CCorePacket::Pack(BinStream& strm) const { strm << server_id_ << server_type_ << msg_id_ << msg_type_ << data_; }UnPack的代码实现:
void CCorePacket::UnPack(BinStream& strm) { strm >> server_id_ >> server_type_ >> msg_id_ >> msg_type_ >> data_; }这连两个函数主要是使用的Revolver Base中BinStream的<<和>>。具体细节可以查看对应的代码。CorePacket打包成网络字节序流代码示例:
BinStream strm; strm << packet; //packet为CorePacket实例
class CConnection : public CEventHandler { public: ... //事件接口 int32_t handle_input(BASE_HANDLER handle); int32_t handle_output(BASE_HANDLER handle); int32_t handle_close(BASE_HANDLER handle, ReactorMask close_mask); int32_t handle_exception(BASE_HANDLER handle); int32_t handle_timeout(const void *act, uint32_t timer_id); //发起一条TCP连接 int32_t connect(const Inet_Addr& remote_addr); int32_t connect(const Inet_Addr& src_addr, const Inet_Addr& dst_addr); //关闭连接 void close(); //发送数据 int32_t send(CCorePacket& packet, bool no_delay = false); int32_t send(const string& bin_stream); ... protected: ... CSockStream sock_stream_; //SOCKET 对象实例 SBuffer sbuffer_; //TCP发送BUFFER,解决报文发送分包问题 RBuffer rbuffer_; //TCP接收BUFFER,解决报文粘包和组包问题 BinStream istrm_; //接收的BinStream流对象 uint8_t server_type_; //0表示客户端 uint32_t server_id_; //对端服务的server ID,如果是客户端为0 Inet_Addr remote_addr_; //远端地址 };在CConnection实现中,会处理CORE_HANDSHAKE CORE_PING CORE_PONG类型的消息,其中CORE_HANDSHAKE会对远端服务做身份校验。CORE_PING和CORE_PONG是用来做连接心跳维系的,一般是1分钟发送一次,如果连接超过4个发送周期没有到对端任何报文,就会断开此连接。
#define SendDispathByID(packet, id)\ CONN_MANAGER()->send_dispatch_by_id(packet, id) #define SendDispathByUDP(packet, id)\ CONN_MANAGER()->send_dispatch_by_udp(packet, id) #define SendUDP(packet, addr)\ CONN_MANAGER()->send_udp(packet, addr) #define SendTCP(packet, conn)\ CONN_MANAGER()->send_tcp(packet, conn)如果本地服务要像远端服务(server_id = 10)发送一个类型为CCorePacket的hello_packet_ 消息:
SendDispathByID(hell_packet_, 10);在这个函数里面首先会检查10这个服务单元节点是否存在,如果存在而且已连接,就直接调用其Connection进行发送,如果未进行连接,就会将报文放在一个缓冲队列中,并发起TCP连接,这个时候是直接返回给上层。连接过程是异步的,如果连接完成,就会发送其缓冲队列中的报文给对端服务单元。这样做的目的是简化上层业务和连接管理之间的耦合,降上层业务的复杂度。
class ICmdTarget { public: ICmdTarget(); virtual ~ICmdTarget(); //定义各种触发参数,例如:SID,mssage class, connection句柄等等 virtual int32_t on_event(uint32_t msg_id, uint32_t sid, CBasePacket* packet, CConnection* connection); //处理UDP消息 virtual int32_t on_event(uint32_t msg_id, uint32_t sid, CBasePacket* packet, const Inet_Addr& remote_addr); protected: virtual CTargetMessageManager* get_message_map() = 0; }; typedef void (ICmdTarget::*TARGET_CALL)(void); typedef map<uint32_t, CMD_MESSAGE_ENTRY> CMD_MESSAGE_MAP;
//设置消息处理器 INIT_MSG_PROCESSOR1(&sample_server_); //设置要处理的消息群体 LOAD_MESSAGEMAP_DECL(SAMPLE_MSG);其中INIT_MSG_PROCESSOR是设置消息处理器,LOAD_MESSAGEMAP_DECL是设置需要隐射的消息分类。
class ICoreFrame { public: ... void init(); void destroy(); void start(bool wan = false); void stop(); //CORE库的运行函数 void frame_run(); //DAEMON CLIENT返回分配好的地址,进行网络绑定,如果是DAEMON void bind_port(uint16_t port); //组件设置 void create_udp(); void create_tcp_listener(); void create_daemon_client(IDaemonEvent* daemon_event, IDaemonConfig* config = NULL); void create_dc_client(); void attach_server_notify(ICoreServerNotify* notify); //提供给上层的事件 virtual void on_init() = 0; virtual void on_destroy() = 0; virtual void on_start() = 0; virtual void on_stop() = 0; protected: CDaemonClient* daemon_client_; //DAEMON CLIENT组件 CCoreTCPListener* listener_; //TCP监听服务组件 CoreUDPHandler* udp_handler_; //UDP服务组件 CCoreDCClient* dc_client_; //DC数据库访问组件 };