vi common.h
#define MYPORT 8800 #define KEYPATH "/tmp/server" #define KEYPROJ 'a' #define START_SERVERS 5 #define MINSPARESERVERS_DFL 5 #define MAXSPARESERVERS_DFL 10 #define MAXCLIENTS_DFL 150 typedef struct node { struct node *next; pid_t pid; int state; int reuse; } Node_t; #define ST_FREE 0L #define ST_BUSY 1L #define IDLE_PID (pid_t)0 struct msgbuf { long mtype; pid_t pid; int state; }; //#endif
vi server.h
/******************************/ void ServerJob();
vi server.c
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include "common.h" extern int sd; extern int msgid; static struct msgbuf buf; static void NoticeState(int state) { buf.mtype=1; buf.state=state; msgsnd(msgid,&buf,sizeof(buf)-sizeof(long),0); } //getsd void ServerJob() { int i; int newsd; struct sockaddr_in his_end; int his_end_len; int ret; buf.pid=getpid(); his_end_len=sizeof(his_end); while(1) { do { newsd=accept(sd,(struct sockaddr *)&his_end,&his_end_len); } while(newsd<0); NoticeState(ST_BUSY); for(i=0;i<10;i++) { write(newsd,".",1); sleep(1); } close(newsd); NoticeState(ST_FREE); } }
vi main.c
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/wait.h> #include "server.h" #include "common.h" int msgid=0; int sd=0; Node_t head={NULL,IDLE_PID,ST_FREE,0}; int nBusy=0; int nFree=0; static int getMsg(void); static int getSocket(); static int ReuseAdd_pid(Node_t *ptr,pid_t pid); static int SetState_pid(Node_t *ptr,pid_t pid,int state); static int DeleteNode_pid(Node_t *ptr,pid_t pid); static int DeleteNode_anyfree(Node_t *ptr); static int AddNode(Node_t *ptr); static void DumpList(Node_t *head); static void ScanList(Node_t *head); static void chld_handle(int s) { pid_t pid; while(pid=waitpid(-1,NULL,WNOHANG)>0) { DeleteNode_pid(&head,pid); } } int main() { int i,ret; struct msgbuf buf; signal(SIGCHLD,chld_handle); msgid=getMsg(); if(msgid==-1) { perror("Get msg queue"); exit(-1); } sd=getSocket(); if(sd==-1) { perror("Get net socket"); exit(-1); } for(i=0;i<START_SERVERS;i++) { ret=AddNode(&head); if(ret==-1) { fprintf(stderr,"AddNode failed.\n"); } else { } } // add test DumpList(&head); while(1) { ret=msgrcv(msgid,&buf,sizeof(buf)-sizeof(long),1,0); fprintf(stderr,"Got a msg from %d\n",buf.pid); if(ret>0) { SetState_pid(&head,buf.pid,buf.state); } ScanList(&head); #ifndef RELEASE DumpList(&head); #endif } } static int getMsg() { key_t key; key=ftok(KEYPATH,KEYPROJ); if(key==-1) { perror("ftok()"); return -1; } msgid=msgget(key,IPC_CREAT|0600); if(msgid==-1) { perror("msgget()"); return -1; } return msgid; } static int getSocket() { int ret; struct sockaddr_in my_end; sd=socket(PF_INET,SOCK_STREAM,0); if(sd==-1) { perror("socket()"); return -1; } int val=1; ret=setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&val,sizeof(val)); /* if(ret==-1) { perror("setsockopt()"); return -1; } */ my_end.sin_family=AF_INET; my_end.sin_port=htons(MYPORT); // my_end.sin_addr.s_addr=inet_addr(); my_end.sin_addr.s_addr=INADDR_ANY; ret=bind(sd,(struct sockaddr *)&my_end,sizeof(my_end)); if(ret==-1) { perror("bind()"); return -1; } ret=listen(sd,10); if(ret==-1) { perror("listen()"); return -1; } return sd; } static int AddNode(Node_t *ptr) { pid_t pid; Node_t *temp; temp=(Node_t *)malloc(sizeof(Node_t)); if(temp==NULL) { perror("malloc()"); return -1; } pid=fork(); if(pid==-1) { perror("fork()"); free(temp); return -1; } if(pid==0) { free(temp); /* TODO: Delete link table */ ServerJob(); } temp->pid=pid; temp->state=ST_FREE; temp->reuse=0; temp->next=ptr->next; ptr->next=temp; nFree++; return pid; } static void DumpList(Node_t *head) { Node_t *temp; temp=head->next; while(temp!=NULL) { if(temp->state==ST_BUSY) { printf("<%d>",temp->pid); } else { printf("%d ",temp->pid); } temp=temp->next; } printf("\n"); printf("nFree=%d\tnBusy=%d\n\n",nFree,nBusy); return; } static int DeleteNode_pid(Node_t *ptr,pid_t pid) { Node_t *temp,*temp_next; int mark=0; temp=ptr; temp_next=temp->next; while(temp_next!=NULL) { if(temp_next->pid==pid) { mark=1; temp->next=temp_next->next; kill(temp_next->pid,SIGTERM); if(temp_next->state==ST_FREE) { nFree--; } else { nFree++; } free(temp_next); break; } temp=temp_next; temp_next=temp->next; } if(mark) { return 0; } else { return -1; } } static int DeleteNode_anyfree(Node_t *ptr) { int mark=0; Node_t *temp,*temp_next; temp=ptr; temp_next=temp->next; while(temp_next!=NULL) { if(temp_next->state==ST_FREE) { mark=1; temp->next=temp_next->next; kill(temp_next->pid,SIGTERM); nFree--; free(temp_next); break; } temp=temp_next; temp_next=temp->next; } if(mark) { return 0; } else { return -1; } } static int SetState_pid(Node_t *ptr,pid_t pid,int state) { Node_t *temp; int mark=0; temp=ptr->next; while(temp!=NULL) { if(temp->pid==pid) { mark=1; if(state==ST_FREE) { nFree++; if(temp->state==ST_BUSY) { nBusy--; } } else if(state==ST_BUSY) { nBusy++; if(temp->state==ST_FREE) { nFree--; } } else { fprintf(stderr,"Unknown state.\n"); return -1; } temp->state=state; break; } temp=temp->next; } if(mark) { return 0; } else { return -1; } } static void ScanList(Node_t *head) { int i,ret,delta; Node_t *temp; int tnFree=0,tnBusy=0; sigset_t now,old; sigemptyset(&now); sigaddset(&now,SIGCHLD); sigprocmask(SIG_BLOCK,&now,&old); temp=head->next; while(temp!=NULL) { ret=kill(temp->pid,0); if(ret==-1) { fprintf(stderr,"Lame node found,delete it.\n"); DeleteNode_pid(temp,temp->pid); } else { if(temp->state==ST_BUSY) { tnBusy++; } else { tnFree++; } } temp=temp->next; } if(nBusy!=tnBusy) { fprintf(stderr,"nBusy corrected(%d).\n",tnBusy); nBusy=tnBusy; } if(nFree!=tnFree) { fprintf(stderr,"nFree corrected(%d).\n",tnFree); nFree=tnFree; } if(nFree<MINSPARESERVERS_DFL) { delta=MINSPARESERVERS_DFL-nFree; if(delta>MAXCLIENTS_DFL-nFree-nBusy) { delta=delta>MAXCLIENTS_DFL-nFree-nBusy; } fprintf(stderr,"%d proces needed to be added.\n",delta); for(;delta>0;delta--) AddNode(head); // AddNode(&head); // } else if(nFree>MINSPARESERVERS_DFL) { } else if(nFree>MAXSPARESERVERS_DFL) { delta=nFree-MAXSPARESERVERS_DFL; fprintf(stderr,"%d proces needed to be deleted.\n",delta); for(;delta>0;delta--) { DeleteNode_anyfree(head); // DeleteNode_anyfree(&head); } } else { /* No adjust needed. */ } sigprocmask(SIG_SETMASK,&old,NULL); return; }