网普技术论坛 网普科技  
» 游客:   网普主页 | 注册 | 登录 | 帮助
 

作者:
标题: 利用INETD实现UDP守护进程 上一主题 | 下一主题
网普科技
网普管理员

网普科技人民公仆


积分 3080
发贴 2863
注册 2004-6-26
来自 网普科技
状态 离线
#1  利用INETD实现UDP守护进程

王月春

在UNIX/LINUX环境中,大部分服务都对应相应的服务器程序,如ftp、telnet等。它们都是有UNIX/LINUX中的INETD守护进程来启动的。

1、创建守护进程的原因

在UNIX/LINUX环境中为什么要使用守护进程呢?这是因为有很多超级服务器的运行是在后台运行且不受终端控制的进程。想要脱离所有终端的原因是守护进程可能是从终端上启动(与从初始化脚本启动相反),在这之后这个终端要能用来执行其他任务。举例来说,如果在某个终端上启动了一个守护进程后从该终端上注销,其他人又从该终端登录,那么任何守护进程的错误信息不应在后面用户的终端会话过程中出现。同样,由终端上的一些键所产生的信号(如中断信号),不应对以前从该终端上启动的任何守护进程造成影响。虽然使服务器程序在后台运行很容易(只要在shell命令行的结尾加一个&符号即可),但是我们还是应该使程序能自动转到后台并且脱离与终端的联系。

2、守护进程的启动

有几种启动守护进程的方法:

①、在系统启动时由系统初始化脚本启动,这些脚本一般在/etc或 /etc/rc开头的目录下,如inetd超级服务器等;
②、许多网络超级服务器是由inetd 启动的,inetd监听网络请求(telnet、ftp等),当请求到来时启动相应的实际服务;
③、cron守护进程按规则定期执行一些程序,由它启动的程序也以守护进程的方式运行;
④、可以使用at命令指定在将来某一时刻执行程序。cron守护进程在到达相应的时间时会启动这些程序,所以它们是以守护进程方式运行的;
⑤、不管在前台还是后台,守护进程也可以在用户终端上启动。

3、利用inetd启动守护进程

在4.3BSD以前的Unix版本中,ftp、telnet等服务是由系统启动时从/etc/rc文件中启动的,它们启动时所做的工作几乎相同:创建套接字,绑定服务端口,等待连接(TCP)或数据报(UDP),然后fork。自进程为客户服务,父进程继续等待下一个请求。这种方式存在两个问题:①这些守护进程有几乎相同的启动代码,首先创建套接字,还要考虑变为守护进程;②每个守护进程在进程表中占有一项,但它们大部分时间处于睡眠状态。

为解决上述两个问题,4.3BSD版本以后引入了inetd这个超级服务器。它可以解决基于TCP或UDP协议的守护服务。引入inetd后,服务器程序所需处理的转化为守护进程的工作交给inetd来做。我们所需要做的工作就是对输入输出进行操作以及配置inetd。

4、inetd超级服务器的配置

配置inetd要涉及两个文件:/etc/services和/etc/inetd.conf 。其中/etc/services包括服务名和监听端口,例如:
inetd_udp_serv 10000,表明inetd_udp_serv这个服务在端口10000进行监听;/etc/inetd.conf 包括服务所使用的套接字种类、协议、执行方式、执行用户、程序路径以及执行程序所带的参数等。如:
inetd_udp_serv dgram udp wait root /usr/bin/inetd_udp_serv,
表明inetd_udp_serv服务是采用数据报套接字、udp协议以循环方式来执行的。在配置完成后,使用以下两条命令,重新启动inetd: #killall inetd,#inetd 。至此,inetd配置完成。需要注意的是,此时在系统中只有相应的套接字,而没有相应的进程。可以使用以下命令进行查看套接字状态:#netstat –a |grep 10000,可以看到如下结果:
Proto Recv-Q Send-Q Local Address Foreign Address Stat
udp 0 0 *.inetd_udp_serv *.*
其中斜体部分为结果,我们可以看出,inetd_udp_serv服务采用udp协议,发送接收队列长度是0,本地地址*.inetd_udp_serv 的含义是本地地址,端口inetd_udp_serv(10000,在/etc/services中定义),远程地址为*.*,表示可以为任意地址和端口。
但是当查看进程时,并没有相应的进程:#ps –eaf|grep inet_udp_serv
只有当客户机发起请求时,服务器收到一个数据报时,在查看才有相应的进程。

5、inetd的工作原理

通过配置inetd,然后查看相应的套接字和进程,可以看出,inetd是这样工作的(针对udp服务):
①、启动时读取/etc/inetd.conf文件并为文件中指定的所有服务创建相应的套接字(流或数据报),inetd能处理的服务的数目依赖于所创建的套接字数目。每个新创建的套接字都被加入到select调用所用到的描述符集中;
②、对每一个套接字调用bind,绑定服务端口(/etc/services中定义),端口号通过调用getservbyname获得;
③、所有套接字建立后,调用select等待它们变为可读,当udp套接字上有数据报到来时变为可读。inetd在大部分时间阻塞在select的调用处;
④、inetd守护进程fork,由子进程处理服务请求;子进程关闭除了要处理的套接字之外的所有描述字,子进程三次调用dup2,把套接字描述字复制到 0、1、2,然后关闭原套接字;以后程序对套接字操作就是对0、1、2进行操作;子进程exec执行相应的服务器程序,并将配置文件中的参数传递。
⑤、因为udp服务器通常设置wait标记,表示inetd在该套接字上再次选择之前,必须等待在该套接字上服务的子进程终止。所以,父进程中的fork 返回时,把子进程的进程号记录下来,这样,在子进程终止时,父进程可以用waitpid的返回值查知是那一个子进程;父进程用FD_CLR宏关闭 select使用的描述字集中与这个套接字对应的位,以便不对该套接字select;当子进程终止时,父进程收到一个SIGCHLD信号,父进程的信号处理程序得到终止子进程的进程号,父进程通过打开描述字集中对应的位恢复对该套接字的select。

6、小结

通过以上分析,可以看出,引入inetd超级服务器后,对服务器所需要的处理大大简化,它处理了所有转变成守护进程所需的步骤,在启动真正服务器程序时套接字已经在stdin、stdout、stderror上打开。我们的程序不必在调用socket、bind、listen以及accept等,因为这些操作inetd已经做了。但同时,也可以看出,使用inetd提供的服务效率相对比较低,因为激活一个服务需要fork和exec两个系统调用,所以,通常在某种服务的使用频率不是很高时,才使用inetd提供的服务。

附程序代码inetd_udp_serv.c,编译配置inetd,如前所述。客户机发起请求,执行方法:
$client ip地址 端口号
如:$client 202.207.124.50 10000(假设服务器为202.207.124.50:10000)
本程序在turbolinux4.0.2调试通过。



天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。



网普科技,优质美国主机服务!
美国Linux主机,美国虚拟主机
支持PHP+MYSQL+cPanel+EMAIL
为用户负责,拒绝反动、赌博及色情内容! QQ:126818

发送QQ消息
2005-6-17 11:25 AM
查看资料  访问主页  发短消息  QQ   编辑帖子  引用回复 顶部
网普科技
网普管理员

网普科技人民公仆


积分 3080
发贴 2863
注册 2004-6-26
来自 网普科技
状态 离线
#2  

inetd_udp_serv.c(文件名)

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>  /*套接字头文件*/
#include<netinet/in.h>
#include<sys/wait.h>
#include<fcntl.h>    /*文件处理头文件*/
#define MAXLEN 65535      /*缓冲区最大长度*/

int main(int argc,char argv[])    /*argc,argv为主程序的参数*/
{
        int sockfd,n;
        int fd;
        struct sockaddr_in serv_addr,cli_addr;/*服务器、客户机套接
字地址*/
        int addr_len,numbytes;
        char buf[MAXLEN];   /*缓冲区,用于接受数据*/
        addr_len=sizeof(struct sockaddr);/*套接字长度*/
        for(;;)
        {        sockfd=0;    /*设置套接字为标准输入*/
                if(numbytes=recvfrom(sockfd,buf,MAXLEN,0,(struct sockaddr *)&cli_addr,&addr_len)==-1)
    /*接收客户机数据报,写入缓冲区,客户机地址写入cli_addr 中*/
                {  perror(“recvfrom”); exit(1);  }
                buf[numbytes]=’\0’;             /*置结束符*/
                fd=open(“recv_text.txt”,O_RDWR|O_CREAT);
                numbytes=write(fd,(char )buf,numbytes);/*将接收到的数据写入
                                               文件*/
                close(fd);
                sockfd=1; /*设置套接字为标准输出*/
                sendto(sockfd,buf,numbytes,0,&cli_addr,sizeof(struct sockaddr));        /*将接收到的数据返还给客户机*/
                }
        close(sockfd);
}

对应的客户机程序:client.c
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<stdio.h>
#define MAX 1024;
int main(int argc,int argv[])
{
        int sockfd,n;
        char buf[MAX];
struct sockaddr_in addr;
        if(argc!=3)  {
                fprintf(stderr,“usage:client ipaddr port\n”);/*用法*/
                exit(1);
        }
        sockfd=socket(AF_INET,SOCK_DGRAM,0);/*创建数据报套接字*/
        if(sockfd<0)         {
                fprintf(stderr,”socket error!\n”);
                exit(1);
        }
        bzero(&addr,sizeof(addr));
        addr.sin_family=AF_INET;
        addr.sin_port=htons(atoi(argv[2]));
        if(inet_aton(argv[1],&addr.sin_addr)<0)  {
                fprintf(atderr,”inet_aton error.\n”);
                exit(1);
        }
        for(;fgets(buf,MAX,stdin)!=NULL;)/*从stdin接受数据*/  {
    sendto(sockfd,buf,strlen(buf),0,addr,sizeof(addr));/*发送数据报*/
                n=recvfrom(sockfd,buf,MAX,0,NULL,NULL);/*接收数据报*/
                buf[n]=0;
                fputs(buf,stdout);  /*将服务器返回的数据报输出*/
        }
        close(sockfd);
}



天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。



网普科技,优质美国主机服务!
美国Linux主机,美国虚拟主机
支持PHP+MYSQL+cPanel+EMAIL
为用户负责,拒绝反动、赌博及色情内容! QQ:126818

发送QQ消息
2005-6-17 11:27 AM
查看资料  访问主页  发短消息  QQ   编辑帖子  引用回复 顶部
茱莉娅
THE BODY SHOP美容顾问

茱莉娅美体小铺


积分 3080
发贴 2863
注册 2009-5-21
来自 茱莉娅美体小铺
状态 离线
#2  赞助商信息The body shop

茱莉娅美体小铺
茱莉娅美体小铺淘宝店
茱莉娅美体小铺


茱莉娅美体小铺淘宝店
2005-6-17 11:27 AM
查看资料  访问主页  发短消息  QQ   编辑帖子  引用回复 顶部


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转:  




Powered by Discuz! 2.5 © 2001-2005 Comsenz Technology Ltd.
Processed in 0.007138 second(s), 7 queries, Gzip enabled
------------------------------------------------------------------------------
本论坛属网普科技交流与技术支持论坛!
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论!
美国主机, 美国虚拟主机, cPanel+PHP+Mysql+Ftp+Email+Zend+GD2+国际域名支持
技术支持 QQ: 126818 EMail & MSN: support[AT]netpu.net
[ 联系我们 ] - [ 网普科技 ]