#include #include #include #include #include #include #include #include #include #include #include #define MAXHOSTNAME 80 //#define DEBUG 0 void reusePort(int sock); int atoi(const char*); int close(int ); int SendData(int, char* ); int Server(int); char *strstr(const char *, const char *); int strncmp(const char *, const char *, size_t ); char *strchr(const char *, int ); int FindUser(char*, char* ) ; ssize_t read(int, void*, size_t); char TITULO[] = "\ +------------------------------------------+\n\ |Charla Server v1.0 by Gabriel Astudillo M.|\n\ +------------------------------------------+\n"; int sockList[64], lastSock=0; int DEBUG; int main(int argc, char* argv[]) { int s; struct sockaddr_in server; struct sockaddr_in from; struct timeval teval; int fromlen; int length; fd_set readfds, readfdsCopy; int n,i; char message[512]; /* Especifica el puerto c/s -debug */ if(argc > 3) { printf("\nError: Demasiados parametros\n"); printf("Uso :%s [puerto] [-debug]\n", *argv); printf(" :%s --help\n\n",*argv); exit(1); } if(argc==2 && strcmp("--help",argv[1]) == 0){ printf("\n\nUso :%s [puerto] [-debug]\n", *argv); printf(" :%s --help\n\n",*argv); printf("\n"); printf("Descripcion de los parametros:\n"); printf(" o puerto : especifica el puerto donde\n"); printf(" el servidor va a escuchar las peticiones.\n"); printf(" o --debug: permite ver ciertos mensajes para comprobar\n"); printf(" las conexiones.\n"); printf(" o --help : estas lineas.\n"); exit(1); } if(argc==3 && strcmp("-debug",argv[2])==0 ){ DEBUG=1; argc--; } else { DEBUG=0; } /* Construct name of socket to send to. */ server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); if (argc == 2) { if(strcmp("-debug",argv[1])!=0) { server.sin_port = htons( (u_short) atoi(argv[1])); } else { DEBUG=1; } } else server.sin_port = htons((u_short) 0); s = socket (AF_INET,SOCK_STREAM,0); reusePort(s); if ( bind( s, (struct sockaddr *)&server, sizeof(server) ) ) { close(s); perror("binding name to stream socket"); exit(-1); } length = sizeof(server); if ( getsockname (s, (struct sockaddr *)&server,&length) ) { perror("getting socket name"); exit(0); } printf("%s\n",TITULO); printf("Charla Server esta en el puerto : %d\n", ntohs(server.sin_port)); listen(s,4); fromlen = sizeof(from); FD_ZERO(&readfdsCopy); FD_SET(s,&readfdsCopy); for(;;){ memcpy(&readfds, &readfdsCopy, sizeof(fd_set)); teval.tv_sec = 0; teval.tv_usec = 100000; //n = select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &teval); n = select(FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, NULL); if (n > 0) { if (FD_ISSET(s, &readfds)) { if(DEBUG==1) { printf("Aceptando una nueva coneccion...\n"); } sockList[lastSock++] = accept(s, (struct sockaddr *)&from, &fromlen); FD_SET(sockList[lastSock-1], &readfdsCopy); /* Envia mensaje de bienvenida * * */ sprintf(message,"%s\nCantidad de usuarios conectados: %d \n\n", TITULO,lastSock); SendData(sockList[lastSock-1], message); } for (i=0; i < lastSock; i++) { if (FD_ISSET(sockList[i], &readfds)) { if (Server(sockList[i]) < 0) { FD_CLR(sockList[i], &readfdsCopy); sockList[i] = sockList[--lastSock]; i--; if(DEBUG==1){ printf("Numero de clientes activos: %d\n", lastSock); } } } } } if(n == 0) { sprintf(message,"<---Mensaje de Control del server--->"); for (i=0; i < lastSock; i++) { SendData(sockList[i], message); } } } } int Server(int psd) { char buf[512]; char *aux; char message[512]; char user_out[512]; int i,rc; /* tomar los datos desde los clientes */ for(;;){ if(DEBUG==1){ printf("\n...server is waiting...\n"); } if( (rc=read(psd, buf, sizeof(buf))) < 0) perror("receiving stream message"); if (rc > 0){ buf[rc]=(char)NULL; if(DEBUG == 1) { printf("Received: %s\n", buf); } if(strstr(buf,"!quit") != (char)NULL) { /* avisar a todos que un * * usuario se ha desconectado */ FindUser(user_out,buf); sprintf(message,"#SERVER# Usuario %s desconectado...\n", user_out); for (i=0; i < lastSock; i++) { SendData(sockList[i], message); } if(DEBUG==1){ printf("Disconnected..\n"); } close (psd); return(-1); } if(strncmp("USER",buf,4) == 0){ /* avisar a todos que un nuevo * * usuario ha ingresado */ aux = (char*)strchr(buf, ':'); sprintf(message,"#SERVER# Usuario <%s> conectado...\n",++aux); for (i=0; i < lastSock; i++) { SendData(sockList[i], message); } } else { /* Enviar los datos recibidos * * a todos los usuarios */ sprintf(message,"%s",buf); for (i=0; i < lastSock; i++) { SendData(sockList[i], message); } } return(1); } else { if(DEBUG==1) { printf("Disconnected..\n"); } close (psd); return(-1); } } } int SendData(int psd, char* data_out) { char buf[512]; strcpy(buf,data_out); if (send(psd, buf, strlen(buf), 0) <0 ) perror("sending stream message"); return(1); } int FindUser(char* line_out, char* line_in) { int l = strlen(line_in); int i; int lim = 0; for(i=0;i') lim=1; } else { break; } } line_out[i++] = '\0'; return(1); } void reusePort(int s) { int one=1; if ( setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *) &one,sizeof(one)) == -1 ) { printf("error in setsockopt,SO_REUSEPORT \n"); exit(-1); } }