- 论坛徽章:
- 1
|
UNIX下利用inetd daemon 管理应用系统的守护进程
中国银行西安市分行信息科技处 胡旋
在当今网际互连中 TCP/IP 已成为事实上的标准,大部分应用程序均采用C/S操作模式、TCP/IP编程并运行。即客户端向服务器发出请求,服务器运行守护进程,随时监听和捕捉客户端的请求并进行相应的处理。对于较大类型的应用系统,如银行综合业务处理系统,将产生各种类型的后台服务进程,这些进程均在无休止的等待,增加系统负载,耗费系统资源,并且管理起来也不方便。
UNIX操作系统为用户提供inetd daemon 进行网络服务管理。它将所有的后台应用程序置于它的管理之下,在客户端没有请求时,所有的后台应用程序都不启动,一旦客户端有特定的请求上来,它将根据/etc/services 和/etc/inetd.conf 文件描述的请求端口号和服务名调动相应的应用程序进行处理,而其它后台应用程序是不启动的。被启动的应用程序完成了特定任务后就终结自己的进程,这就减轻了系统负载,节约了系统资源,极大地提高了系统效率,是实现应用系统网络互连的一个实用工具。
inetd daemon 在开机时由/etc/rc.tcpip文件启动,一旦inetd daemon 启动即从 /etc/inetd.conf 文件中读取它的配置信息,然后在特定的套接字上监听连接请求,该文件的作用是告诉 inetd daemon 各端口号上的请求如何处理。即该服务采用何种套接字类型,是字节流还是数据报,采用什么协议(TCP/UDP),应用程序等待否,在监听套接字之前是否释放套接字,应用程序的名字、参数及路径等。整个流程可用下图表示:
inetd daemon 在运行中可通过SRC命令(startsrc stopsrc lssrc等)进行控制。所以,可以很方便地对后台应用程序进行管理。
下面简要介绍如何在inetd daemon 中增加一个新的后台处理程序,假定该程序是电话银行的后台处理程序tbankd。
1.修改 /etc/services 文件,增加新的应用程序的端口号和服务名。
服务名 端口号/网络类型
tbank 3000/tcp
2.修改 /etc/inetd.conf 配置文件,增加新的一行配置:
服务名套接字类型 采用的协议 等待否 用户名 应用程序及路径 参数
tbank stream tcp nowait root /u0/tbank/bin/tbankd
3.应用程序编程注意事项
服务器上的应用程序 tbankd 从标准输入 stdin 中读取客户端发来的请求数据,返回的处理信息也写入 stdin。
4.重新启动 inetd daemon
先用 stopsrc -s inetd 命令关闭 inetd daemon,
再用 startsrc -s inetd 命令启动.
或用refresh -s inetd 省去关闭启动过程,直接通知inetd daemon 配置文件已改变,启用新的配置文件。
5.查看inetd daemon 运行状况:
键入lssrc -a 后系统显示:
Subsystem Group PID Status
inetd tcpip 26912 active
表示 inetd daemon 已正常启动 进程号为 26912
6.inetd daemon 运行流程图 :
本地主机 远程主机 从标准输入
前台通信请求方 服务器方 接收请求
read(0)
创建套接字 后台处理程序一 处理
向标准输入
建立链接 inetd daemon 返回处理结果
write(0)
向服务器发出
请求数据报文 后台处理程序二 ...
.
阻塞等待服务器 .
返回数据报文 .
收到结果报文 后台处理程序N ...
其它处理
7.程序实例 :
该程序是一个实用的基本模型,用户可在此基础上开发出自己的应用程序。
- /*client 客户端程序*/
- #include <stdio.h>;
- #include <sys/types.h>;
- #include <sys/times.h>;
- #include <sys/socket.h>;
- #include <netinet/in.h>;
-
- #define HEADLEN 6
- main(argc,argv)
- int argc;
- char ** argv;
- {
- int sockfd;
- struct sockaddr_in serv_addr;/*存服务器方的地址*/
- char info[4096],head[7];
- int infolen;
- int rc;
-
- if (argc!=2)
- {
- fprintf(stderr,"client ipaddress\n");
- exit(-1);
- }
- /*参数是服务器的IP地址*/
- bzero((char *)&serv_addr, sizeof(serv_addr));
- /*服务器地址变量清0*/
- serv_addr.sin_family = AF_INET;
- /*网络地址类型使用ARPA internet 地址*/
- serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
- /*服务器IP地址转换为长整型IP地址, 并赋予地址结构变量*/
- serv_addr.sin_port=htons(6000);
- /*与服务器相同的IP端口号, 经主机字节顺序到网络字节顺序的转换*/
- if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- /*创建TCP协议的字节流套接字*/
- {
- fprintf(stderr, "Client : Can not open stream socket\n");
- exit(-1);
- }
- /*与服务进程建立连接*/
- if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
- {
- fprintf(stderr,"err connect ....\n");
- exit(-1);
- }
- /*此时连接已建立, 可通过对套接字的读写实现通信*/
- /*客户进程向服务进程发送请求信息*/
- sprintf(info,"000026向服务器发出查询张三的请求");
- infolen=strlen(info);
- if ( (rc=write(sockfd, info, infolen)) == -1 )
- fprintf(stderr, "TCPSend failed !!\n");
- /*接受服务器返回的头信息*/
- memset(head,0,sizeof(head));
- if (( rc=read(sockfd, head, HEADLEN)) == -1
- || rc<HEADLEN
- || (infolen=atoi(head))<=0 )
- {
- fprintf(stderr, "read head failed rc:%d!!\n",rc);
- exit(-1);
- }
- /*接受服务器返回的报文信息*/
- memset(info,0,sizeof(info));
- if ( (rc=read(sockfd, info, infolen)) == -1 )
- fprintf(stderr, "TCPRecv failed !!\n");
- /*客户进程接收服务进程返回的帐户信息*/
- fprintf(stderr,"%s\n",info);
- shutdown(sockfd, 2);
- close(sockfd);
- }
-
-
- /*tbankd后台服务程序*/
- #include <stdio.h>;
- #define HEADLEN 6
- FILE *fp_log;
-
- main(argc,argv)
- int argc;
- char ** argv;
- {
- char info[1024],head[7];
- int infolen;
- int rc;
- char * send_info;
-
- fp_log=fopen("/_tbank.log","a");
- memset(head,0,sizeof(head));
- /*接受客户机发来的头信息*/
- if (( rc=read(0, head, HEADLEN)) == -1
- || rc<HEADLEN
- || (infolen=atoi(head))<=0 )
- {
- fprintf(fp_log, "read head failed rc:%d!!\n",rc);
- exit(-1);
- }
- memset(info,0,sizeof(info));
- if ((rc=read(0, info, infolen)) == -1 || rc<infolen )
- /*接受客户机发来的信息*/
- {
- fprintf(fp_log, "read info failed !!\n");
- exit(-1);
- }
- fprintf(fp_log,"收到的客户端的请求:%s\n",info);
- send_info="000021张三当前余额1000.00元";
- /*向客户机发送该帐户信息*/
- infolen=strlen(send_info);
- if ((rc=write(0, send_info, infolen) )== -1)
- fprintf(fp_log, "TCPSend failed !!\n");
- close(fp_log);
- }
复制代码 |
|