文章《快速创建你的服务器程序》讲述了基于 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); // 单独运行方式 } else mp.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 # 表示该服务进程池的最大进程数为 2 master_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
github: https://github.com/acl-dev/aclQQ 群:242722074
相关推荐
然而,在某些情况下,Ping 命令可能会报错,例如“ping: cap_set_proc: 不允许的操作”。这是一种 capability 相关的错误,发生在 Ping 命令试图使用 RAW SOCKET 权限时。该错误的原因是普通用户没有足够的权限来...
LINUX下通过_proc和gdb感染进程的实现.pdf
1. **编写驱动程序**:首先,你需要编写一个内核模块,作为设备驱动程序。这个驱动程序包含了与硬件交互的代码,以及必要的操作函数,如打开、关闭、读取、写入等。 2. **注册设备**:在驱动程序中,使用`register_...
multi_proc_wrong.c 下载后直接编译运行
标题中的“该程序使用_proc机制检查反映机器平均负载,进程资源利用等方面的各种内核值”表明,这是一个关于系统监控和性能分析的程序。在Linux操作系统中,_proc虚拟文件系统(procfs)是一个非常重要的组成部分,...
微机原理与接口技术课件:第4章_2过程定义伪指令PROC、ENDP.ppt
oracle_proc程序设计
### Oracle_ProC编程入门知识点详解 #### 一、Oracle Pro*C简介 **Oracle Pro*C**是一种结合了C语言和SQL的编程方式,主要用于开发Oracle数据库应用程序。它将过程化的C语言与非过程化的SQL语言完美结合,使得...
这可能是开发者理解ProC语法、学习如何在Unix环境下编写和调用ProC程序的关键参考资料。而"www.pudn.com.txt"可能是一个链接到更多资源的文本文件,或者是一份在pudn.com网站上找到这个资料的说明。 学习ProC的过程...
multi_proc.c 下载后直接编译运行
本文档主要介绍达梦数据库DM8_PROC的使用手册,包括DM对PRO*C的支持、PRO*C程序的编写、dpc_new工具的使用等。下面是本文档的知识点摘要: 1. DM对PRO*C的支持:DM支持嵌入式SQL语法,包括对PRO*C的支持。PRO*C是...
在Linux系统编程中,信号量(Semaphore)是一种用于进程间通信的重要机制,它提供了一种控制多个进程对共享资源访问的方式。"sem_proc_consume.rar_consume" 提供的是一段简单的C语言代码示例,旨在帮助学习者理解...
6. **锁机制**:为了保证数据一致性,当多个进程同时访问procfs中的I2O设备文件时,`i2o_proc.c`可能会实现必要的锁机制,确保并发安全。 7. **异常处理**:在处理用户请求时,`i2o_proc.c`可能会包含异常处理代码...
标题中的"hda_proc.rar_high"暗示了我们正在讨论与Intel高清音频编码解码器(Codec)相关的编程接口,特别是“hda_proc”可能是驱动程序或库中的一个关键组件,用于处理与High Definition Audio(HDA)相关的进程。...
### DM7_PROC使用手册知识点概览 #### 一、概述 **1.1 功能简介** DM7_PROC使用手册详细介绍了达梦数据库对于PRO*C的支持情况。PRO*C是一种允许开发者将C语言代码与SQL语句混合编写的工具,主要用于简化数据库...
### DM7_PROC使用手册知识点概览 #### 一、概述 **DM7_PROC使用手册**是针对达梦数据库管理系统(DM)中对于PRO*C支持的一个详细介绍。本手册旨在帮助开发人员、测试工程师、技术支持人员及数据库管理员更好地理解和...
2. `/proc/pid/status`:这里的`pid`是进程ID,每个运行的进程都有对应的`status`文件,其中包含进程的内存使用情况。比如`VmSize`表示进程的虚拟内存大小,`VmRSS`表示常驻集大小,即实际使用的物理内存。 3. `/...