#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\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<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\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;
}
}
}
} |