/*This program accepts connections from clients as well as from servers. The server will announces its availability and the services it offers and on which IP address/port. Dispatcher stored this information in queues (different queues according to different services). When a client ask for a service, dispatcher will look up the according queue (in round-robin rotaiton), and give the server's ip address and port number back to the client.*/ #include "service.h" char buff[150]; char reply[150]; int sockfd; int acsd; struct sockaddr_in my_addr; struct sockaddr_in client_addr; int len=sizeof(client_addr); int yes=1; int myport=3498; /*fix a port for dispatcher to 3498 */ s_list *sum_s=NULL; s_list *product_s=NULL; int main(void) { char func[15]; /*to contain the function client requested.*/ char addr[50]; /*to contain the server's ip address.*/ int port; /*to contain the server's port number.*/ int status=0; s_list *tmp; /*create a socket, bind it to myport and listen on this port. if status is 1,then fails.*/ if(status=bind_remote(myport,&sockfd,&my_addr)==1) exit(1); while(1) { /*accept incoming connections to the dispatcher.*/ if ( (acsd = accept(sockfd, (struct sockaddr *) &client_addr, &len)) < 0) { perror("accept()"); exit(1); } /*receive message from the connection.*/ if(recv(acsd,buff,100,0)<0) { perror("recv"); exit(1); } /*If it is a message from client.*/ if(strcmp(strtok(buff," "),"client")==0) { printf("Received info from client %s at %d.\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); strcpy(buff,strtok(0," ")); /*if the function requested is sum,look up sum list.*/ if(strcmp(buff,"sum")==0) searchlist(&sum_s); /*if the function requested is product,look up product list.*/ else if(strcmp(buff,"product")==0) searchlist(&product_s); printf("Sending server info to client at %s at %d ......", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); /*send the server's ip address and port number (stored in reply) to client.*/ if(send(acsd, (void *) reply, strlen(reply) + 1, 0)<0) { perror("send"); exit(1); } printf("Done!\n"); } /*If it is a message from server.*/ else { printf("Received info from server %s at %d.\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); strcpy(func,strtok(0," ")); /*get the services provided by server.*/ strcpy(addr,strtok(0," ")); /*get the ip address of server.*/ port=atoi(strtok(0," ")); /*get the port number of server.*/ /*create a new node */ tmp=(s_list *)malloc(sizeof(s_list)); strcpy(tmp->addr,addr); tmp->port=port; tmp->next=NULL; /*if the service is sum,put it in the sum list.*/ if(strcmp(func,"sum")==0) addlist(&sum_s,tmp); /*if the service is product,put it int he product list.*/ else if(strcmp(func,"product")==0) addlist(&product_s,tmp); /*if the services provided by server are both sum and product, put it into both sum and product list.*/ else if(strcmp(func,"both")==0) { addlist(&sum_s,tmp); tmp=(s_list *)malloc(sizeof(s_list)); strcpy(tmp->addr,addr); tmp->port=port; addlist(&product_s,tmp); } /*if the service warns the dispatcher it is no longer available, delete it from the according list.*/ else if(strcmp(func,"exit")==0) { deletelist(&sum_s,addr,port); deletelist(&product_s,addr,port); } } close(acsd); } close(sockfd); return (0); } /*A function implement round-robin rotation.*/ void roundrobin(s_list **list) { s_list *tmp,*head; tmp=*list; if (*list==NULL ||(*list)->next==NULL) return; /*go through the list, until reaches the end.*/ while(tmp->next!=NULL) { tmp=tmp->next; } /*pick up the first node, put it to the end of the queue.*/ head=(*list)->next; tmp->next=*list; (*list)->next=NULL; (*list)=head; return; } /*A function to get the first node of the list,and round-robin the list once so that we will choose the next node next time.*/ void searchlist(s_list ** list) { s_list *tmp=*list; if(*list==NULL) strcpy(reply,"Not Available."); else { sprintf(reply,"%s %d",(*list)->addr,(*list)->port); roundrobin(list); } } /*A function to add a node to the end of the list.*/ void addlist(s_list **list,s_list *elem) { s_list *tmp; tmp=*list; if(tmp==NULL) { *list=elem; return; } /*go throught the list, until reaches the end.*/ while(tmp->next!=NULL) { tmp=tmp->next; } /*add the node to the end of the list.*/ tmp->next=elem; return; } /*A fucntion to delete a node according to the ip address and port number. */ void deletelist(s_list **list,char*addr, int port) { s_list *cur,*pre; cur=*list; pre=NULL; if(cur==NULL) { printf("No server is working.\n"); return; } while(cur!=NULL) { /*if we have found the node to delete.*/ if(strcmp(cur->addr,addr)==0&& (cur->port==port)) { if(cur==*list) *list=cur->next; else if(cur!=NULL) pre->next=cur->next; printf("deleting %s\n",inet_ntoa((*(struct in_addr*)gethostbyname(cur->addr)->h_addr))); return; } pre=cur; cur=cur->next; } /*After going through the list,such node is not found.*/ printf("No such server at all.\n"); return; }