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