Advertisement
Guest User

Untitled

a guest
Jun 19th, 2017
508
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.36 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement