使用 acl::master_proc 类编写多进程服务器程序

来源:互联网 发布:仿链家房产源码 编辑:程序博客网 时间:2024/05/22 03:51

      文章《快速创建你的服务器程序》讲述了基于 C 语言版本的 acl 服务器框架下如何开发多进程服务器应用程序。本文则讲述了基于 C++ 语言的 acl_cpp 服务器框架下如何开发多进程服务器应用程序,当然 acl_cpp 下的服务器框架内部也是基于 acl 的服务器框架的。关于基于acl_master 的服务器程序设计原理,请参考 《协作半驻留式服务器程序开发框架》。

      一、类成员函数说明

      master_proc 是一个纯虚类,其中定义的接口需要子类实现,如下:

 

/** * 纯虚函数:当接收到一个客户端连接时调用此函数 * @param stream {aio_socket_stream*} 新接收到的客户端异步流对象 * 注:该函数返回后,流连接将会被关闭,用户不应主动关闭该流 */virtual void on_accept(socket_stream* stream) = 0;

     master_proc 类提供了两个函数:

 

/** * 开始运行,调用该函数是指该服务进程是在 acl_master 服务框架 * 控制之下运行,一般用于生产机状态 * @param argc {int} 从 main 中传递的第一个参数,表示参数个数 * @param argv {char**} 从 main 中传递的第二个参数 */void run_daemon(int argc, char** argv);/** * 在单独运行时的处理函数,用户可以调用此函数进行一些必要的调试工作 * @param addr {const char*} 服务监听地址 * @param conf {const char*} 配置文件全路径 * @param count {int} 当该值 > 0 时,则接收的连接次数达到此值且完成 *  后,该函数将返回,否则一直循环接收远程连接 * @return {bool} 监听是否成功 */bool run_alone(const char* addr, const char* conf = NULL, int count = 1);

      master_proc 类实例当在生产环境下(由 acl_master 进程统一控制调度),用户需要调用 run_daemon 函数;如果用户在开发过程中需要手工进行调试,则可以调用 run_alone 函数。

      master_proc 的基类 master_base 的几个虚接口如下:

 

/** * 当进程切换用户身份前调用的回调函数,可以在此函数中做一些 * 用户身份为 root 的权限操作 */virtual void proc_pre_jail() {}/** * 当进程切换用户身份后调用的回调函数,此函数被调用时,进程 * 的权限为普通受限级别 */virtual void proc_on_init() {}/** * 当进程退出前调用的回调函数 */virtual void proc_on_exit() {}// 在 run_alone 状态下运行前,调用此函数初始化一些配置

 

      二、示例

 

// master_proc.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include "lib_acl.hpp"// 字符串类型的配置项static char *var_cfg_debug_msg;static acl::master_str_tbl var_conf_str_tab[] = {{ "debug_msg", "test_msg", &var_cfg_debug_msg },{ 0, 0, 0 }};// 布尔类型的配置项static int  var_cfg_debug_enable;static acl::master_bool_tbl var_conf_bool_tab[] = {{ "debug_enable", 1, &var_cfg_debug_enable },{ 0, 0, 0 }};// 整数类型的配置项  static int  var_cfg_io_timeout;static acl::master_int_tbl var_conf_int_tab[] = {{ "io_timeout", 120, &var_cfg_io_timeout, 0, 0 },{ 0, 0 , 0 , 0, 0 }};static void (*format)(const char*, ...) = acl::log::msg1;//////////////////////////////////////////////////////////////////////////using namespace acl;class master_proc_test : public master_proc{public:master_proc_test() {}~master_proc_test() {}protected:/** * 基类纯虚函数:当接收到一个客户端连接时调用此函数 * @param stream {aio_socket_stream*} 新接收到的客户端异步流对象 * 注:该函数返回后,流连接将会被关闭,用户不应主动关闭该流 */virtual void on_accept(socket_stream* stream){if (stream->format("hello, you're welcome!\r\n") == -1)return;while (true){if (on_read(stream) == false)break;}}bool on_read(socket_stream* stream){string buf;if (stream->gets(buf) == false)  // 读一行数据{format("gets error: %s", acl::last_serror());return false;}if (buf == "quit"){stream->puts("bye!");return false;}if (buf.empty()){if (stream->write("\r\n") == -1){format("write 1 error: %s", acl::last_serror());return false;}}else if (stream->write(buf) == -1){format("write 2 error: %s, buf(%s), len: %d",acl::last_serror(), buf.c_str(), (int) buf.length());return false;}else if (stream->write("\r\n") == -1){format("write 3 client error: %s", acl::last_serror());return false;}return true;}// 基类虚函数:服务进程切换用户身份前调用此函数virtual void proc_pre_jail(){format("proc_pre_jail\r\n");}// 基类虚函数:服务进程切换用户身份后调用此函数virtual void proc_on_init(){format("proc init\r\n");}// 基类虚函数:服务进程退出前调用此函数virtual void proc_on_exit(){format("proc exit\r\n");}private:};//////////////////////////////////////////////////////////////////////////int main(int argc, char* argv[]){master_proc_test mp;// 设置配置参数表mp.set_cfg_int(var_conf_int_tab);mp.set_cfg_int64(NULL);mp.set_cfg_str(var_conf_str_tab);mp.set_cfg_bool(var_conf_bool_tab);// 开始运行if (argc >= 2 && strcmp(argv[1], "alone") == 0){format = (void (*)(const char*, ...)) printf;mp.run_alone("127.0.0.1:8888", NULL, 5);  // 单独运行方式}elsemp.run_daemon(argc, argv);  // acl_master 控制模式运行return 0;}

      这是一个简单的提供 echo 行服务的服务器程序,可以支持多个并发连接,而且可以通过配置文件控制所启动的最大进程数、进程空闲时间等控制参数,因为 acl 中的服务器框架都是半驻留的,所以既可以保证运行效率,又能够在空闲释放系统资源。该例子所在目录:acl_cpp/samples/master_proc。

      需要注意的是,master_proc 内部是单例的,即要求该类的对象只能有一个,否则内部自动产生断言。只所以没有采用单例模板来设计单例,主要是为了不对外暴露 acl 库中的接口,使使用 acl_cpp 库的用户不必关心 acl 库的头文件在哪儿。

      三、配置文件及程序安装

      打开 acl_cpp/samples/master_proc/single_echo.cf 配置文件,就其中几个配置参数说明一下:

 

## 由 acl_master 用来控制服务进程池的配置项# 为 no 表示启用该进程服务,为 yes 表示禁止该服务进程master_disable = no# 表示本服务器进程监听 127.0.0.1 的 5002 端口master_service = 127.0.0.1:5002# 表示是 TCP 套接口服务类型master_type = inet# 进程程序名master_command = master_proc# 表示该服务进程池的最大进程数为 2master_maxproc = 2# 进程日志记录文件,其中 {install_path} 需要用实际的安装路径代替master_log = {install_path}/var/log/single_echo.log
# 每个进程实例处理连接数的最大次数,超过此值后进程实例主动退出single_use_limit = 250# 每个进程实例的空闲超时时间,超过此值后进程实例主动退出single_idle_limit = 180

 

 

      例如当 acl_master 服务器框架程序的安装目录为:/opt/acl,则:

      /opt/acl/libexec: 该目录存储服务器程序(acl_master 程序也存放在该目录下);

      /opt/acl/conf:该目录存放 acl_master 程序配置文件 main.cf;

      /opt/acl/conf/service:该目录存放服务子进程的程序配置文件,该路径由 main.cf 文件指定;

      /opt/acl/var/log:该目录存放日志文件;

      /opt/acl/var/pid:该目录存放进程号文件。

      该程序编译通过后,需要把可执行程序放在 /opt/acl/libexec 目录下,把配置文件放在 /opt/acl/conf/service 目录下。

      在 /opt/acl/sh 下有启动/停止 acl_master 服务进程的控制脚本;运行脚本:./start.sh,然后请用下面方法检查服务是否已经启动:

      ps -ef|grep acl_master # 查看服务器控制进程是否已经启动

      netstat -nap|grep LISTEN|grep 5002 # 查看服务端口号是否已经被监听

      当然,您也可以查看 /opt/acl/var/log/acl_master 日志文件,查看服务进程的启动过程及监听服务是否正常监听。

 

      可以命令行如下测试:telnet 127.0.0.1 5002

       原文地址

       acl_cpp 下载

       acl_cpp 的编译与使用

       更多文章

       个人微博:http://weibo.com/zsxxsz

       QQ 群:242722074

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 眼睛里膜起来了怎么办 眼睛一边大一边小怎么办 眼白膜鼓起来了怎么办 主持问答环节没人提问怎么办 转学原学校不给怎么办 村长借东西不还怎么办 村长不上报建房申请怎么办 村长不上报建房手续申请怎么办 村长不给村民盖章怎么办? 找村干部办事难怎么办 洪洞县村长不给我盖章怎么办 睾丸穿刺取精只配到6个胚胎怎么办 孩子一只耳朵听不到声音怎么办 孕早期孕囊生长慢怎么办 试管2次不着床怎么办? pescm球员年龄大了怎么办 实况足球俱乐部经理球员老了怎么办 你不是我的菜怎么办 苹果平板电脑耳机有回音怎么办 obs直播有电流音怎么办 语音里网吧很吵怎么办 电脑k歌有延迟怎么办 想开个跆拳道馆怎么办营业执照? 壶嘴拐弯处漏水怎么办 裂纹茶壶嘴坏了怎么办 小孩刚上学怕她上火怎么办 在幼儿园小朋友不愿叠衣服怎么办 孩子在家听话幼儿园不听话怎么办 变魔术时观众说看过这个怎么办 孕妇8个月摔跤了怎么办 孩子吃了残奶怎么办 小米手机变卡了怎么办 主持时说错话了怎么办 小鲜肉老了不红怎么办 同学聚会大家玩手机你怎么办 率土之滨被掠夺怎么办 戒指戴手上取不下来怎么办 择离开我我该怎么办 解小手解不出来怎么办 学生把班里的班费弄丢了怎么办 班里选的班长成绩差怎么办