stallion5632 / license-services

基于boost.asio的tcp 局域网认证服务

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

license-server

基于boost.asio的tcp 局域网认证服务

0、工程结构

  • loghelper:简单的日志组件;
  • json_message_processor: json消息的encode和decode;
  • daemon: 守护进程;
  • conf: 工程和消息配置;
  • license-client:license客户端,以动态链接库的方式提供;
  • license-server:license服务端,内部集成看门狗服务(工程中看门狗相关代码已移除)

1、消息格式

消息格式为:

消息 长度(BYTES) 结构 描述
Header 4 SyncBytes 格式:0x09, 0x6f, 0x01, 0x01,表示不同设备之间的交互
Header 4 FullMessageLength 数据总长度,包括SyncBytes和FullMessageLength
Header 4 MessageSeq 消息序列 seq ,递增
Header 4 MeaageType 消息类型(消息号),如登录消息或发送消息消息
Header 4 StringBody 消息字符流长度,可能是json流、xml流以及普通字符流
Header 12 Reserved 保留字段,总共12字节
Body StringBodyLength StringBody 消息体( json或xml或普通字符串数据),该字段长度可能为0
Body FullMessageLength - 32 - StringBodyLength BinaryData 二进制数据,该字段长度可能为0

注: 消息头总共32个字节(包括SyncBytes和FullMessageLength),消息体长度StringBodyLength是已知的,而二进制数据长度计算得到(FullMessageLength - 32 - StringBodyLength)。

2、license控制

  • license-server默认有个maxLicenseNum,即最大支持客户端个数;
  • 客户端认证一次,maxLicenseNum减1,直到maxLicenseNum ==0;
  • 客户端断开tcp连接或者停止服务,maxLicenseNum加1

3、网络库

  • license-server和 license-client底层均使用boost.asio的异步方式。

  • license-client已做隐藏,调用方可以不依赖于boost库。

  • 参考asio/example/cpp03/timeouts/server.cpp实现tcpserver

  • tcpclient实现参考path_to_boost/libs/asio/example/cpp03/chat/chat_client.cpp和path_to_boost/libs/asio/example/cpp03/timeouts/async_tcp_client.cpp

4、License-Client

  • C++客户端模块最终以动态链接库方式提供。

  • license-client提供给外部动态链接库,接口有:

    	// 开始认证服务
    	// cfg - 客户端的配置
    	// messageTypes - 消息映射表,必须和server保持一致
    	// cb - 看门狗状态的回调函数
    	void start(ClientConfig& cfg, MessageType_t& messageTypes, std::function<void(int)> cb);
    
    	// 停止认证服务
    	void stop();
    
    	void sendHeartbeatReq();
    	void sendLoginReq();
    	void sendLogoutReq();
    	void sendGetDogStatusReq();

客户端各模块关系

5、License-Server

各模块关系

各模块关系

如图为各模块关系,简要说明:

  • 为了减少对外暴露接口,使用PIMPL方式对外隐藏实现;

  • 每个tcpclient对应一个TcpServerSession对象,通过SessionManager集中管理;

  • 将具体业务转移到MessageHandler中处理,JsonMessageProcessor专门用于json消息的encode和decode;

  • main函数包含了程序配置加载和消息表映射读取,这部分也可以抽成单独模块。

消息触发

消息触发

如图在TcpClientImpl中async_read消息:

  • 当读到32字节消息头时,触发handlerReaderHeader,在消息预处理完成后,分发给注册的MessageHandler::onReadHeader处理;

  • 当读到完整的TcpMessage后,触发handleReadBoay,预处理完成后,分发给onReadBody处理。

消息处理流程

消息处理流程

如图,收到LoginReq消息后的处理流程:

  • 首先,读取消息头。检查消息头是否正确,如果正确继续往下执行;
  • 其次,读取消息体。在readBody中分发消息到具体处理函数,在onLoginReq中调用dogService.getCurrentStatus。
  • 最后,组装回复的LoginRsp消息,使用TcpServerSession的write发送消息。

6、心跳和保活

  • 做了双向心跳,即客户端和服务端各自独立做心跳,目的是保证license能及时释放。
    • 客户端定时检查是否收到服务端的心跳回复(request),如果连续3次没有收到心跳回复,则认为tcp连接断开;
    • 服务端定时检查是否收到客户端的心跳申请(respone),如果连续3次没有收到心跳申请,则认为tcp连接断开;
    • 服务端和客户端的定时器间隔必须保持一致
  • 客户端有连接断开重连机制,可以选择是否开启。

7、守护进程设计

几个限制条件:

  • 守护进程和工作进程必须在同一目录;
  • 只支持启动一个工作进程,只是定时检查pid是否存在
  • 启动时,首先检查本地是否存在同名进程,如有则先杀掉。
  • linux平台可能存在僵死进程情况,需要调用waitpid处理。
  • 工作流程示意图如下:

守护进程工作流程

About

基于boost.asio的tcp 局域网认证服务

License:MIT License


Languages

Language:C++ 84.7%Language:CMake 13.6%Language:C 1.4%Language:Batchfile 0.2%