1、概述
本节主要描述了以进程池模式创建服务器程序的过程,而该进程池框架是以 acl_master 模板为管理进程,以 acl_single_server 单一进程池模式为半驻留进程池模板创建的。该进程池模型有如下特点:
1.1)半驻留进程池特征;
1.2)一个网络连接对应一个工作进程。
2、创建过程(以 acl_project/samples/master/single_echo 为例,ACL库是跨平台的,但 acl_master 服务器框架仅能运行在UNIX平台下)
在acl_project/samples/master/single_echo/ 目录下存放着一个以 acl_single_server 为服务器模型的echo服务程序。在该目录下应该有 main.c, app_log.c, app_log.h, Makefile, Makefile.elib 四个文件,所需要修改的只是 main.c 文件,其它几个文件无须修改。
2.1)编写源文件
a)包含 ACL 库的头文件: #include "lib_acl.h"
b)调用服务函数 acl_single_server_main() 并注册相关函数:
函数原型:void acl_single_server_main(int argc, char **argv, ACL_SINGLE_SERVER_FN service,...);
argc, argv: 是 main() 入口的两个参数;
service :是用户自己的服务工作函数指针,该函数是以注册函数的方式注册进服务框架模板并由服务框架调用的;
...:是一些不定参数,这些参数都是可选的,这些不定参数是以“类型:指针”的方式传递给服务框架的,由服务框架根据类型自动进行分析,常用类型有:
ACL_MASTER_SERVER_INT_TABLE--为int类型的配置项集合的结构数组指针(该类型与由框架读取用户所需要的配置项相关);
ACL_MASTER_SERVER_STR_TABLE--字符串类型的配置项集合的结构数组指针(该类型与由框架读取用户所需要的配置项相关);
ACL_MASTER_SERVER_BOOL_TABLE--布尔类型的配置项集合的结构数组指针(该类型与由框架读取用户所需要的配置项相关);
ACL_MASTER_SERVER_PRE_INIT--该类型表明后面的参数为一函数指针,服务进程启动后会自动切换成普通用户身份,该类型所代表的函数会在服务切换成普通用户身份前进行调用;
ACL_MASTER_SERVER_POST_INIT--该类型表明后面的参数为一函数指针,当服务框架将该服务工作进程切换成普通用户身份后所调用的函数;
ACL_MASTER_SERVER_PRE_ACCEPT--该类型表明后面的参数为一函数指针,当服务框架监听到监听套接口上有新的客户端连接到达,在用户 accept()接受该连接之前可以先回调用户的注册函数,此函数指针即为该回调函数;
ACL_MASTER_SERVER_EXIT--该类型表明后面的参数为一函数指针,当该服务进程退出所回调的用户的注册函数。
2.2)源文件展示
/* main.c */ #include "lib_acl.h" #include "app_log.h" #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> static char *var_cfg_single_banner; static int var_cfg_single_timeout; static ACL_CONFIG_INT_TABLE __conf_int_tab[] = { { "single_timeout", 60, &var_cfg_single_timeout, 0, 0 }, { 0, 0, 0, 0, 0 }, }; static ACL_CONFIG_STR_TABLE __conf_str_tab[] = { { "single_banner", "hello, welcome!", &var_cfg_single_banner }, { 0, 0, 0 }, }; static void __service(ACL_VSTREAM *stream, char *service, char **argv acl_unused) { const char *myname = "__service"; char buf[4096]; int n, ret; /* * Sanity check. This service takes no command-line arguments. */ if (argv[0]) acl_msg_fatal("%s(%d)->%s: unexpected command-line argument: %s", __FILE__, __LINE__, myname, argv[0]); acl_msg_info("%s(%d)->%s: service name = %s, rw_timeout = %d", __FILE__, __LINE__, myname, service, stream->rw_timeout); acl_msg_info("total alloc: %d", acl_mempool_total_allocated()); do { acl_watchdog_pat(); n = acl_vstream_readline(stream, buf, sizeof(buf) - 1); if (n == ACL_VSTREAM_EOF) { acl_msg_info("%s(%d)->%s: read over", __FILE__, __LINE__, myname); break; } ret = acl_vstream_writen(stream, buf, n); if (ret != n) { acl_msg_info("%s(%d)->%s: write error = %s", __FILE__, __LINE__, myname, strerror(errno)); break; } } while (0); } static void __pre_accept(char *name acl_unused, char **argv acl_unused) { } static void __pre_jail_init(char *name acl_unused, char **argv acl_unused) { acl_mempool_open(512000000, 1); /* 是否采用 libcore 的日志记录 */ #ifdef HAS_LIB_CORE # ifdef USE_LIBCORE_LOG app_set_libcore_log(); # endif #endif } static void __post_jail_init(char *name acl_unused, char **argv acl_unused) { } static void service_exit(char *service acl_unused, char **argv acl_unused) { #ifdef HAS_LIB_CORE # ifdef USE_LIBCORE_LOG app_libcore_log_end(); # endif #endif } int main(int argc, char *argv[]) { acl_single_server_main(argc, argv, __service, ACL_MASTER_SERVER_INT_TABLE, __conf_int_tab, ACL_MASTER_SERVER_STR_TABLE, __conf_str_tab, ACL_MASTER_SERVER_PRE_INIT, __pre_jail_init, ACL_MASTER_SERVER_PRE_ACCEPT, __pre_accept, ACL_MASTER_SERVER_POST_INIT, __post_jail_init, ACL_MASTER_SERVER_EXIT, service_exit, 0); exit (0); }
2.3) 配置文件:single_echo.cf
service single
{
# 进程是否禁止运行
master_disable = no
# 服务地址及端口号
master_service = :5003
# 服务监听为域套接口
# master_service = single_echo.sock
# 服务类型
master_type = inet
# master_type = unix
# 是否只允许私有访问, 如果为 y, 则域套接口创建在 {install_path}/var/log/private/ 目录下,
# 如果为 n, 则域套接口创建在 {install_path}/var/log/public/ 目录下,
master_private = n
master_unpriv = n
# 是否需要 chroot: n -- no, y -- yes
master_chroot = n
# 每隔多长时间触发一次,单位为秒(仅对 trigger 模式有效)
master_wakeup = -
# 最大进程数
master_maxproc = 10
# 进程程序名
master_command = single_echo
# 进程启动参数,只能为: -u [是否允许以某普通用户的身份运行]
# master_args =
# 进程日志记录文件
master_log = {install_path}/var/log/single_echo.log
# 传递给服务子进程的环境变量, 可以通过 getenv("SERVICE_ENV") 获得此值
# master_env = logme:FALSE, priority:E_LOG_INFO, action:E_LOG_PER_DAY, flush:sync_flush, imit_size:512,\
# sync_action:E_LOG_SEM, sem_name:/tmp/single_echo.sem
# 每个进程实例处理连接数的最大次数,超过此值后进程实例主动退出
single_use_limit = 250
# 每个进程实例的空闲超时时间,超过此值后进程实例主动退出
# single_idle_limit = 180
# 记录进程PID的位置(对于多进程实例来说没有意义)
single_pid_dir = {install_path}/var/pid
# 进程运行时所在的路径
single_queue_dir = {install_path}/var
# 读写超时时间, 单位为秒
single_rw_timeout = 1800
# 读缓冲区的缓冲区大小
single_buf_size = 8192
# 进程运行时的用户身份
single_owner = root
# single_in_flow_delay = 1
# single_owner = owner
# 用 select 进行循环时的时间间隔
# 单位为秒
# single_delay_sec = 1
# 单位为微秒
# single_delay_usec = 5000
# single_daemon_timeout = 1800
}
2.4)编译源文件
生成 single_echo 可执行程序
make
2.5)拷贝文件
将 single_echo 拷贝至 acl_project/dist/master/libexec/linux32 (假设操作系统是LINUX 32位平台的) 目录,将 single_echo.cf 拷贝至acl_project/dist/master/conf/service/ 目录,从而将 single_echo 置于 acl_master 守护管理进程的控制范围内。
2.6) 安装
cd acl_project/dist/master; chmod 755 setup.sh; ./setup.sh /opt/acl
2.7)启动框架管理控制进程(acl_master)
/opt/acl/sh/start.sh
2.8)手工测试
telnet 127.0.0.1 5003
看是否正常连接服务器,如果连接成功,则随意输入一些字符然后按回车发送,看服务器是否将所发送的数据回显给发送者;如果连接不成功或服务器未正常回显,请查看日志文件:/opt/acl/var/log/single_echo,并找出出错原因。
个人微博:http://weibo.com/zsxxsz
下载:http://sourceforge.net/projects/acl/
svn:svn checkout svn://svn.code.sf.net/p/acl/code/trunk acl-code
github:https://github.com/acl-dev/acl/
QQ 群:242722074
国内镜像:http://git.oschina.net/zsxxsz/acl
相关推荐
cxf-dosgi-ri-singlebundle-distribution-1.4.0.jar
- 安装:将 `ack-2.14-single-file` 文件复制到你的 PATH 路径下的任意位置,或者直接将其保存在常用目录,如 `$HOME/bin`,并赋予执行权限:`chmod +x ack-2.14-single-file`。 - 使用:一旦安装完成,你就可以在...
在这个项目"kalman-filter-in-single-object-tracking-main.zip"中,开发者可能已经编写了一个完整的Python脚本来演示如何在视频每一帧上应用卡尔曼滤波进行目标跟踪。 首先,理解卡尔曼滤波的基本原理是必要的。...
2.2.13 Packet Tracer - Point-to-Point Single-Area OSPFv2 Configuration.pka Cisco Packet Tracer 思科模拟器 正确答案文件 可直接上交正确答案文件 本答案版权归mewhaku所有,严禁再次转载!!! Copyright @...
qikj-QJ_Single-masterQJ_OneLotus.zip开源代码
2. 电离层延迟校正:单频接收机通常采用模型化的方法来估算电离层延迟,如Klobuchar模型或更高级的模型,以提高定位精度。 五、SDR在GPS和Galileo接收器中的应用 1. 接收机设计:通过SDR技术,可以实现一个接收器...
2.7.1 Packet Tracer - Single-Area OSPFv2 Configuration 正确答案文件 可直接上交正确答案文件 本答案版权归mewhaku所有,严禁再次转载!!! Copyright @mewhaku 2022 All Rights Reserved
2.4.11-packet-tracer---modify-single-area-ospfv2_zh-CN.pka
"Laravel开发-eloquent-single-state-marking-store"是一个专为Laravel设计的扩展,旨在支持单一状态标记存储,其灵感来源于Symfony的工作流程组件。这个项目的目标是帮助开发者更好地管理和跟踪对象的状态,特别是...
离线安装包,亲测可用
当我们谈论"unity-airsim-single-uav-fly"时,我们关注的是如何在Unity环境中利用AirSim插件来实现一架无人机的飞行模拟。 首先,我们要了解Unity的基础。Unity是基于C#编程语言的,提供了一个全面的游戏开发框架,...
ShopEx是中国知名的电子商务软件提供商,其“ShopEx Single”是一款专为中小企业设计的一站式网上商城解决方案...对于打算下载和使用该版本的用户,确保你的服务器环境符合要求,并参考官方文档以获得最佳的使用体验。
在“magnum-singles-master”中,单头库可能包含了用Magnum引擎构建的独立模型或者组件,这些资源可以被开发者直接引入到自己的项目中,快速实现3D模型的展示和交互。 使用Magnum引擎进行3D建模时,开发者可以利用...
Sigrity-PowerDC Single-BoardPackageETCo-Simulation Tutorial.zip 本章解释了PowerDC Thermal工作流的主要功能和优势,并介绍了本教程的结构。 具体内容如下: ■ PowerDC热能产品概述 ■ PowerDC电/热联合仿真的...
标题中的“single_phase_DSOGI_PLL.rar_DSOGI- PLL_DSOGI-FLL_DSOGI-PLL_SINGLE”指的是一个关于单相DSOGI锁相环(Phase-Locked Loop, PLL)的模拟项目,其中可能包含了DSOGI无稳态振荡器(Doubly Stable Oscillator...
标题中的"Single-Image-Dehazing-Four-Methods-master_滤波_single_"表明这是一个关于单图像去雾技术的项目,其中可能包含了四种不同的滤波方法,专门用于改善图像的清晰度,尤其适用于处理因大气散射导致的图像模糊...
正在安装npm install --save-dev gulp-vue-single-file-component用法var vueComponent = require ( 'gulp-vue-single-file-component' ) ;gulp . task ( 'vue' , function ( ) { return gulp . src ( './js/...
State-of-the-art_Single_Shot_MultiBox_Detector_in__SSD.TensorFlow
Ajax-cosmetics-check-single-page-app.zip,在react、redux和react路由器中实现spa搜索引擎,ajax代表异步javascript和xml。它是多种web技术的集合,包括html、css、json、xml和javascript。它用于创建动态网页,其中...
在这个场景中,"Laravel开发-laravel-single-table-inheritance"是一个专门针对这个概念的包,它提供了集成到Laravel中的单表继承模型,支持使用Eloquent ORM(对象关系映射),也就是所谓的"雄辩"。 首先,让我们...