SHARE
TWEET

Untitled

a guest Jun 19th, 2017 114 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.      
  2.  
  3.  
  4. /**
  5. *************************************************************
  6. * @file servtcp.c
  7. * @brief Breve descripción
  8. * Ejemplo de un cliente TCP usando threads
  9. *
  10. *
  11. * @author Gaspar Fernández <blakeyed@totaki.com>
  12. * @version 0.1Beta
  13. * @date 13 ene 2011
  14. * Historial de cambios:
  15. *   20110113 - Versión inicial
  16. *
  17. *
  18. *************************************************************/
  19.  
  20. #include <fcntl.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include <errno.h>
  24. #include <stdio.h>
  25. #include <netinet/in.h>
  26. #include <resolv.h>
  27. #include <sys/socket.h>
  28. #include <sys/types.h>
  29. #include <sys/wait.h>
  30. #include <arpa/inet.h>
  31. #include <unistd.h>
  32. #include <pthread.h>
  33. #include <string.h>
  34.  
  35. /** Puerto  */
  36. #define PORT       7000
  37.  
  38. /** Número máximo de hijos */
  39. #define MAX_CHILDS 3
  40.  
  41. /** Longitud del buffer  */
  42. #define BUFFERSIZE 512
  43.  
  44. int AtiendeCliente(int socket, struct sockaddr_in addr);
  45. int DemasiadosClientes(int socket, struct sockaddr_in addr);
  46. void error(int code, char *err);
  47. void reloj(int loop);
  48.  
  49. int main(int argv, char** argc){
  50.  
  51.     int socket_host;
  52.     struct sockaddr_in client_addr;
  53.     struct sockaddr_in my_addr;
  54.     struct timeval tv;      /* Para el timeout del accept */
  55.     socklen_t size_addr = 0;
  56.     int socket_client;
  57.     fd_set rfds;        /* Conjunto de descriptores a vigilar */
  58.     int childcount=0;
  59.     int exitcode;
  60.  
  61.     int childpid;
  62.     int pidstatus;
  63.  
  64.     int activated=1;
  65.     int loop=0;
  66.     socket_host = socket(AF_INET, SOCK_STREAM, 0);
  67.     if(socket_host == -1)
  68.       error(1, "No puedo inicializar el socket");
  69.    
  70.     my_addr.sin_family = AF_INET ;
  71.     my_addr.sin_port = htons(PORT);
  72.     my_addr.sin_addr.s_addr = INADDR_ANY ;
  73.  
  74.    
  75.     if( bind( socket_host, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 )
  76.       error(2, "El puerto está en uso"); /* Error al hacer el bind() */
  77.  
  78.     if(listen( socket_host, 10) == -1 )
  79.       error(3, "No puedo escuchar en el puerto especificado");
  80.  
  81.     size_addr = sizeof(struct sockaddr_in);
  82.  
  83.  
  84.     while(activated)
  85.       {
  86.     reloj(loop);
  87.     /* select() se carga el valor de rfds */
  88.     FD_ZERO(&rfds);
  89.     FD_SET(socket_host, &rfds);
  90.  
  91.     /* select() se carga el valor de tv */
  92.     tv.tv_sec = 0;
  93.     tv.tv_usec = 500000;    /* Tiempo de espera */
  94.    
  95.     if (select(socket_host+1, &rfds, NULL, NULL, &tv))
  96.       {
  97.         if((socket_client = accept( socket_host, (struct sockaddr*)&client_addr, &size_addr))!= -1)
  98.           {
  99.         loop=-1;        /* Para reiniciar el mensaje de Esperando conexión... */
  100.         printf("\nSe ha conectado %s por su puerto %d\n", inet_ntoa(client_addr.sin_addr), client_addr.sin_port);
  101.         switch ( childpid=fork() )
  102.           {
  103.           case -1:  /* Error */
  104.             error(4, "No se puede crear el proceso hijo");
  105.             break;
  106.           case 0:   /* Somos proceso hijo */
  107.             if (childcount<MAX_CHILDS)
  108.               exitcode=AtiendeCliente(socket_client, client_addr);
  109.             else
  110.               exitcode=DemasiadosClientes(socket_client, client_addr);
  111.  
  112.             exit(exitcode); /* Código de salida */
  113.           default:  /* Somos proceso padre */
  114.             childcount++; /* Acabamos de tener un hijo */
  115.             close(socket_client); /* Nuestro hijo se las apaña con el cliente que
  116.                          entró, para nosotros ya no existe. */
  117.             break;
  118.           }
  119.           }
  120.         else
  121.           fprintf(stderr, "ERROR AL ACEPTAR LA CONEXIÓN\n");
  122.       }
  123.  
  124.     /* Miramos si se ha cerrado algún hijo últimamente */
  125.     childpid=waitpid(0, &pidstatus, WNOHANG);
  126.     if (childpid>0)
  127.       {
  128.         childcount--;   /* Se acaba de morir un hijo */
  129.  
  130.         /* Muchas veces nos dará 0 si no se ha muerto ningún hijo, o -1 si no tenemos hijos
  131.          con errno=10 (No child process). Así nos quitamos esos mensajes*/
  132.  
  133.         if (WIFEXITED(pidstatus))
  134.           {
  135.  
  136.         /* Tal vez querremos mirar algo cuando se ha cerrado un hijo correctamente */
  137.         if (WEXITSTATUS(pidstatus)==99)
  138.           {
  139.             printf("\nSe ha pedido el cierre del programa\n");
  140.             activated=0;
  141.           }
  142.           }
  143.       }
  144.     loop++;
  145.     }
  146.  
  147.     close(socket_host);
  148.  
  149.     return 0;
  150. }
  151.  
  152.     /* No usamos addr, pero lo dejamos para el futuro */
  153. int DemasiadosClientes(int socket, struct sockaddr_in addr)
  154. {
  155.     char buffer[BUFFERSIZE];
  156.     int bytecount;
  157.  
  158.     memset(buffer, 0, BUFFERSIZE);
  159.    
  160.     sprintf(buffer, "Demasiados clientes conectados. Por favor, espere unos minutos\n");
  161.  
  162.     if((bytecount = send(socket, buffer, strlen(buffer), 0))== -1)
  163.       error(6, "No puedo enviar información");
  164.    
  165.     close(socket);
  166.  
  167.     return 0;
  168. }
  169.  
  170. int AtiendeCliente(int socket, struct sockaddr_in addr)
  171. {
  172.  
  173.     char buffer[BUFFERSIZE];
  174.     char aux[BUFFERSIZE];
  175.     int bytecount;
  176.     int fin=0;
  177.     int code=0;         /* Código de salida por defecto */
  178.     time_t t;
  179.     struct tm *tmp;
  180.  
  181.     while (!fin)
  182.       {
  183.  
  184.     memset(buffer, 0, BUFFERSIZE);
  185.     if((bytecount = recv(socket, buffer, BUFFERSIZE, 0))== -1)
  186.       error(5, "No puedo recibir información");
  187.  
  188.     /* Evaluamos los comandos */
  189.     /* El sistema de gestión de comandos es muy rudimentario, pero nos vale */
  190.     /* Comando TIME - Da la hora */
  191.     if (strncmp(buffer, "TIME", 4)==0)
  192.       {
  193.         memset(buffer, 0, BUFFERSIZE);
  194.  
  195.         t = time(NULL);
  196.         tmp = localtime(&t);
  197.  
  198.         strftime(buffer, BUFFERSIZE, "Son las %H:%M:%S\n", tmp);
  199.       }
  200.     /* Comando DATE - Da la fecha */
  201.     else if (strncmp(buffer, "DATE", 4)==0)
  202.       {
  203.         memset(buffer, 0, BUFFERSIZE);
  204.  
  205.         t = time(NULL);
  206.         tmp = localtime(&t);
  207.  
  208.         strftime(buffer, BUFFERSIZE, "Hoy es %d/%m/%Y\n", tmp);
  209.       }
  210.     /* Comando HOLA - Saluda y dice la IP */
  211.     else if (strncmp(buffer, "HOLA", 4)==0)
  212.       {
  213.         memset(buffer, 0, BUFFERSIZE);
  214.         sprintf(buffer, "Hola %s, ¿cómo estás?\n", inet_ntoa(addr.sin_addr));
  215.       }
  216.     /* Comando EXIT - Cierra la conexión actual */
  217.     else if (strncmp(buffer, "EXIT", 4)==0)
  218.       {
  219.         memset(buffer, 0, BUFFERSIZE);
  220.         sprintf(buffer, "Hasta luego. Vuelve pronto %s\n", inet_ntoa(addr.sin_addr));
  221.         fin=1;
  222.       }
  223.     /* Comando CERRAR - Cierra el servidor */
  224.     else if (strncmp(buffer, "CERRAR", 6)==0)
  225.       {
  226.         memset(buffer, 0, BUFFERSIZE);
  227.         sprintf(buffer, "Adiós. Cierro el servidor\n");
  228.         fin=1;
  229.         code=99;        /* Salir del programa */
  230.       }
  231.     else
  232.       {    
  233.         sprintf(aux, "ECHO: %s\n", buffer);
  234.         strcpy(buffer, aux);
  235.       }
  236.  
  237.     if((bytecount = send(socket, buffer, strlen(buffer), 0))== -1)
  238.       error(6, "No puedo enviar información");
  239.       }
  240.  
  241.     close(socket);
  242.     return code;
  243. }
  244.  
  245. void reloj(int loop)
  246. {
  247.   if (loop==0)
  248.     printf("[SERVIDOR] Esperando conexión  ");
  249.  
  250.   printf("\033[1D");        /* Introducimos código ANSI para retroceder 2 caracteres */
  251.   switch (loop%4)
  252.     {
  253.     case 0: printf("|"); break;
  254.     case 1: printf("/"); break;
  255.     case 2: printf("-"); break;
  256.     case 3: printf("\"); break;
  257.     default:            /* No debemos estar aquí */
  258.       break;
  259.     }
  260.  
  261.   fflush(stdout);       /* Actualizamos la pantalla */
  262. }
  263.  
  264. void error(int code, char *err)
  265. {
  266.   char *msg=(char*)malloc(strlen(err)+14);
  267.   sprintf(msg, "Error %d: %s\n", code, err);
  268.   fprintf(stderr, msg);
  269.   exit(1);
  270. }
RAW Paste Data
Pastebin PRO Summer Special!
Get 40% OFF on Pastebin PRO accounts!
Top