介绍守护进程XINETD与SOCKET程序的含义

http://tech.ddvip.com   2007年06月26日    社区交流

内容摘要:Xinetd提供被动式的超级服务,也就是服务程序是被使用端所启动,平时则无须存在。

  7.重新实现的XINETD超级守护程序

  A.程序利用上面的原理在思路上重新实现了超级守护进程。

  B.程序在一些地方只是概念性的代码,完全实现还有待补充。

  C.程序能演示XINETD 的功能,但是在注释有BUG 和NOTE 的地方还需改进

  D.这是一个总结性的资料,参考了“利用INETD实现UDP守护进程“和“www.douzhe.com“上的文章。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<errno.h>
#include <sys/ioctl.h>
//为每一个服务分配一个包含socket,及路径的信息结构。
struct param{
 int  sock;   //BIND的套接字  
 char path[256]; //服务程序 路径 
 pid_t pid ;   //CHILD 进程ID  
 struct param *next; 
}
fd_set readfds;
struct param *phead,*ptail,*p;
/*
响应子进程结束的信号函数;
如果服务中wait=yes;
则bind socket 必须等到子进程结束才能监听下一个请求
*/
void signal_handler(int signum)
{
 pid_t pid;
 pid= waitpid(-1,NULL,WUNTRACED);
 for(p=phead;p!=NULL;p=p->next)
   if(p->pid==pid)
{
     //FD_SET(p->sock,&readfds);
     printf("child exit pid= %d
",pid);
     break;
    }
 signal(SIGCHLD,signal_handler);
}  
int main(int argc,char *argv[])
{
 int sock,ss;
 int nret;
 int sock_len;
 struct sockaddr_in addr; 
 struct sockaddr_in addr_clt; 
 FILE *file;
 fd_set testfds;
 sock_len=sizeof(addr);
 
 p=(struct param*)malloc(sizeof(struct param));
 ptail=p;
 phead=NULL;
 
 p->sock=socket(AF_INET,SOCK_STREAM,0);
   // file=fopen("/etc/xinetd.conf","r");
   // while(1)//省略从"/etc/xinetd.conf"文件中读每一个服务并启动
 {
 addr.sin_family=AF_INET;
 addr.sin_addr.s_addr=htonl(INADDR_ANY);
 addr.sin_port=htons(9734);//从“/etc/service”文件中读服务的端口号 getservbyname;
 bind(p->sock,(struct sockaddr *)&addr,sock_len);
 listen(p->sock,5);
  FD_ZERO(&readfds);
  FD_SET(p->sock,&readfds);
 
  strcpy(p->path,"~/socket/");//省略从"/etc/xinetd.conf"文件中读每一个服务的路径
  if(phead==NULL)
  {
   p->next=NULL;
   phead=ptail=p;    
   printf("phead==null
");
  }
 else
  {
   ptail->next=p;
   ptail=p;
   ptail->next=NULL;
  }
  printf("path=%s,sock=%d
",phead->path,phead->sock);
}
 
 while(1)
{
 int fd;
 int clientfd;
 int n;
 pid_t pid;
 int flag=0;
 testfds=readfds;
 
  nret=select(FD_SETSIZE,&testfds,NULL,NULL,NULL);
  //if(nret<0){perror(strerror(errno));exit(5);}// bug 1:如果子进程END,会显示“interrupt system call”错误。
  
  for(fd=0;fd<FD_SETSIZE;fd++)
  if(FD_ISSET(fd,&readfds))
   { //bug 2:第一次接收到串“sock addr=3.190.0.64,client sock=4”,以后用LOOPBACK 连接返回为"127.0.0.1"
clientfd=accept(fd,(struct sockaddr*)&addr_clt,&n);
    printf("sock addr=%s,client sock=%d
",inet_ntoa(addr_clt.sin_addr),clientfd);
     pid=fork();
    switch(pid)
{
case -1:
  perror("error");         
  exit(5);  
    case 0:
          
  //dup2(clientfd,stdin);
     //dup2(clientfd,stdout);
     //dup2(clientfd,stderr);
     //close(clientfd);
  for(p=phead;p!=NULL;p=p->next)
  if(p->sock==fd)
      { printf("child runing
");
  //execve(); //note 1:未调用SERVER PATH(FILE)    
  } 
      sleep(1);    
  exit(5);    
    default:// >0
  close(clientfd);
  if(flag) //note 2: 由service name 的wait 标志决定
  FD_CLR(fd,&readfds);      
      for(p=phead;p!=NULL;p=p->next)
   if(p->sock==fd)
    {  
         p->pid=pid;
         printf("sock:%d, child pid=%d
",p->sock,p->pid);
    } 
      signal(SIGCHLD,signal_handler);//note 3:放到开始,还是这儿呢?   
     break;   
}
   }
 
}
}

责编:豆豆技术应用

正在加载评论...