<span id='sca4'></span>
  • <i id='sca4'></i>

    <ins id='sca4'></ins>

    <code id='sca4'><strong id='sca4'></strong></code>

    1. <tr id='sca4'><strong id='sca4'></strong><small id='sca4'></small><button id='sca4'></button><li id='sca4'><noscript id='sca4'><big id='sca4'></big><dt id='sca4'></dt></noscript></li></tr><ol id='sca4'><table id='sca4'><blockquote id='sca4'><tbody id='sca4'></tbody></blockquote></table></ol><u id='sca4'></u><kbd id='sca4'><kbd id='sca4'></kbd></kbd>
      1. <acronym id='sca4'><em id='sca4'></em><td id='sca4'><div id='sca4'></div></td></acronym><address id='sca4'><big id='sca4'><big id='sca4'></big><legend id='sca4'></legend></big></address>
        <i id='sca4'><div id='sca4'><ins id='sca4'></ins></div></i>

        1. <fieldset id='sca4'></fieldset>
          <dl id='sca4'></dl>
          1. 介绍守护进程XINETD与SOCKET程序的含义

            • 时间:
            • 浏览:1
            • 来源:124软件资讯网

              1.Xinetd提供被动式的超级服务

                也就是服务法式是被使用端所启动  ,平时则无须存在  。例如  ,ftp, telnetd, pop3,imap, auth等等  ,这些服务没有人使用时 ,无须启动 。此外  ,xinetd将socket转换成stdin/stdout ,因而使得网路服务程式设计大大简化  ,您可以只用printf及fgets便可完成处置惩罚很庞大的网路协定  。


              2.一个简朴的服务法式 goodie

              #include
              #include
              #include

              char *cmds[]={
              "help",
              "say",
              "hello",
              "bye",
              "exit",
              NULL
              };

              int getcmd(char *cmd)
              {
              int n=0;
              while (cmds[n]!=NULL) {
              if (strncasecmp(cmd,cmds[n],strlen(cmds[n]))==0) return n;
              n++;
              }
              return -1;
              }

              void main(void)
              {
              char buf[1024];
              int ok;

              printf("Welcome to goodie service! ");
              fflush(stdout);

              ok=0;
              do {
              while (fgets(buf,1023,stdin)==NULL);
              switch (getcmd(buf)) {
              case -1: printf("Unknown command! "); break;
              case 0:
              printf("How may I help you, sir? ");
              int j=0;
              while(cmds[j++]!=NULL)printf(” %s\t\t“,cmds[j-1]);
              break;
              case 1: printf("I will say %s",&buf[3]); break;
              case 2: printf("How're you doing today? "); break;
              case 3: printf("Si ya, mate! "); ok=1; break;
              case 4: printf("Go ahead! "); ok=1; break;
              }
              fflush(stdout);
              } while (!ok);

              }

              3.设置文件


              在/etc/services 中加入如下项


              goodie 12345/tcp


              服务名是 goodie 服务端口是 12345 服务类型是 TCP


              在/etc/xinetd.d目录下新检服务文件 goodie


              输入内容:

              service goodie
              {
              socket_type=stream
              protocal =tcp
              wait =no
              server = /{goodie dir}/goodir
              disable =no #初始化为开启服务监听
              }


              4.启动服务

              先制止服务

              killall xinetd

              启动服务

              /usr/sbin/xinetd -f /etc/xinetd.conf


              5.开启终端毗连

              telnet localhost 12345
              6.xinetd 的事情原理

              通过设置xinetd ,然后检察响应的套接字和历程  ,可以看出  ,

              xinetd是这样事情的(针对tcp服务)
              A.启动时读取/etc/xinetd.conf文件并为文件中指定的所有服务建立响应的套接字(流或数据报)  ,xinetd能处置惩罚的服务的数目依赖于所建立的套接字数目  。每个新建立的套接字都被加入到select挪用所用到的形貌符集中  。

              B.对每一个套接字挪用bind ,绑定服务端口(/etc/services中界说)  ,端口号通过挪用getservbyname获得  。

              C.所有套接字建设后  ,挪用select等候它们变为可读  ,当tcp套接字上有数据报到来时变为可读  。xinetd在大部门时间壅闭在select的挪用处;

              D.xinetd守护历程fork  ,由子历程处置惩罚服务请求;子历程关闭除了要处置惩罚的套接字之外的所有形貌字  ,子历程三次挪用dup2 ,把套接字形貌字复制到0、1、2  ,然后关闭原套接字;以后法式对套接字操作就是对0、1、2举行操作;子历程exec执行响应的服务器法式 ,并将设置文件中的参数通报 。

              E. 由于tcp服务器通常设置nowait标志  ,表现xinetd在该套接字上再次选择之前  ,必须等候在该套接字上服务的子历程终止 。以是  ,父历程中的fork返回时  ,把子历程的历程号记载下来  ,这样 ,在子历程终止时  ,父历程可以用waitpid的返回值查知是那一个子历程;父历程用FD_CLR宏关闭select使用的形貌字集中与这个套接字对应的位 ,以便差池该套接字select;当子历程终止时  ,父历程收到一个SIGCHLD信号  ,父历程的信号处置惩罚法式获得终止子历程的历程号  ,父历程通过打开形貌字集中对应的位恢复对该套接字的select 。


              7.重新实现的XINETD超级守护法式


              A.法式使用上面的原理在思绪上重新实现了超级守护历程  。


              B.法式在一些地方只是观点性的代码 ,完全实现另有待增补  。

              C.法式能演示XINETD 的功效  ,可是在注释有BUG 和NOTE 的地方还需革新

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

              #include
              #include
              #include

              #include
              #include

              #include
              #include
              #include

              #include
              #include
              //为每一个服务分配一个包罗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;


              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\n",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\n");
              }
              else
              {
              ptail->next=p;
              ptail=p;
              ptail->next=NULL;

              }
              printf("path=%s,sock=%d\n",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 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\n",     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 \n");
              //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\n",p->sock,p->pid);
              }
              signal(SIGCHLD,signal_handler);//note 3:放到最先  ,照旧这儿呢  ?
              break;
              }

              }

              }

              }