#include #include #include #include #include #include #include #include #include #include #include #include #include struct chatxstructure { fd_set master; fd_set read_fds; int fdmax; int listener; int newfd; }control; struct chatxvars { int nbytes; int yes; int addrlen; int i; int j; int PORT; int y; int z; }*vars; void init(); void informserver(int fd,char *tempbuf,int nbytes); int main(int argc,char *argv[]) { extern struct chatxstructure control; extern struct chatxvars *vars; struct sockaddr_in myaddr; struct sockaddr_in remoteaddr; char *buf; char *mesg; if(argc != 2) { fprintf(stderr,"usage : %s -> port \a\n",argv[0]); return -1; } vars=(struct chatxvars*)malloc(sizeof(struct chatxvars)); buf=(char *)malloc(256); init(); vars->PORT=atoi(argv[1]); FD_ZERO(&control.master); FD_ZERO(&control.read_fds); // get the control.listener if((control.listener = socket(AF_INET,SOCK_STREAM,0))==-1) { perror("socket"); return -1; } // lose the pesky "address already in use" error message if(setsockopt(control.listener,SOL_SOCKET,SO_REUSEADDR,&vars->yes,sizeof(int))==-1) { perror("setsockopt"); return -1; } myaddr.sin_family=AF_INET; myaddr.sin_addr.s_addr=htonl(INADDR_ANY); myaddr.sin_port=htons(vars->PORT); memset(&(myaddr.sin_zero),'\0',8); if(bind(control.listener,(struct sockaddr *)&myaddr,sizeof(myaddr))==-1) { perror("bind"); return -1; } if(listen(control.listener,10)==-1) { perror("listen"); return -1; } // add the control.listener to the control.control.master set FD_SET(control.listener,&control.master); control.fdmax=control.listener; // mail loop mesg=(char *)malloc(128); for(;;) { control.read_fds=control.master; // copy it if(select(control.fdmax+1,&control.read_fds,NULL,NULL,NULL)==-1) { perror("select"); return -1; } for(vars->i=0;vars->i<=control.fdmax;vars->i++) { if(FD_ISSET(vars->i,&control.read_fds)) { // we got one!! if(vars->i==control.listener) { vars->addrlen=sizeof(remoteaddr); if((control.newfd=accept(control.listener,(struct sockaddr *)&remoteaddr, &vars->addrlen))==-1) { perror("accept"); } else { FD_SET(control.newfd,&control.master); // add to control.master set if(control.newfd > control.fdmax) { // keep track of the maximum control.fdmax=control.newfd; } printf("selectserver : new connection from %s on " "socket %d\n",inet_ntoa(remoteaddr.sin_addr),control.newfd); if(vars->y!=0) { sprintf(mesg,"\nuser from %s signed in!\n", inet_ntoa(remoteaddr.sin_addr)); for(vars->z=0;vars->z<=control.fdmax;vars->z++) { if(FD_ISSET(vars->z,&control.master)) if(vars->z!=control.listener && vars->z!= control.newfd) if(send(vars->z,mesg,strlen(mesg),0)==-1) perror("send"); } } vars->y++; } } else { if((vars->nbytes=recv(vars->i,buf,sizeof(buf),0))<=0) { if(vars->nbytes==0) { //connection closed printf("selectserver : socket %d hung up\n",vars->i); sprintf(mesg,"\nuser from %s signed out!\n", inet_ntoa(remoteaddr.sin_addr)); vars->y--; for(vars->z=0;vars->z<=control.fdmax;vars->z++) { if(FD_ISSET(vars->z,&control.master)) if(vars->z!=control.listener && vars->z != vars->i) if(send(vars->z,mesg,strlen(mesg),0)==-1) perror("send"); } }else { perror("recv"); } //control.newfd, close(vars->i); // bye! FD_CLR(vars->i,&control.master); // remove from control.master set } else { if( (vars->y)>1 ) { //we got some data from a client informserver(vars->i,buf,vars->nbytes); for(vars->j=0;vars->j<=control.fdmax;vars->j++) { if(FD_ISSET(vars->i,&control.master)) { //except the control.listener and ourselves if(vars->j!=control.listener && vars->j != vars->i) { if(send(vars->j,buf,vars->nbytes,0)==-1) { perror("send"); } } } } } else { sprintf(mesg,"server-client[%s]socket=%d : room's empty!\n", inet_ntoa(remoteaddr.sin_addr),vars->i); if(send(vars->i,mesg,strlen(mesg),0)==-1) { perror("send"); } } } } } } } return 0; } void init() { extern struct chatxvars *var; vars->yes=1; vars->PORT=0; vars->y=0; vars->z=0; } void informserver(int fd,char *tempbuf,int nbytes) { tempbuf[nbytes]='\0'; fprintf(stdout,"data transimission from client on socket %d\n",fd); fprintf(stdout,"data=%s\n",tempbuf); }