Herramientas de usuario

Herramientas del sitio


sockets-jo

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
sockets-jo [2014/10/29 15:41] – [Servidor de Eco Mono-Cliente] lmateusockets-jo [2018/08/16 13:04] (actual) – [Proxy genérico] lmateu
Línea 373: Línea 373:
 </code> </code>
  
-=== Ejercicio resuelto: servidor para cat remoto === +=== Ejercicio resuelto: Servidor para cat remoto ===
- +
-Estudie los programas servidor-cat.c y cat-remoto.c en [[http://users.dcc.uchile.cl/~lmateu/CC3301/download/serv-cat.zip|este link]].  Esta es la solución de la +
-[[http://users.dcc.uchile.cl/~lmateu/CC3301/tareas/t4-2012-2.pdf|tarea 4 del semestre Primavera de 2012]].+
  
 +Estudie los programas servidor-cat.c y cat-remoto.c en [[http://users.dcc.uchile.cl/~lmateu/CC3301/download/serv-cat.zip|este link]].  Esta es la solución de la [[http://users.dcc.uchile.cl/~lmateu/CC3301/tareas/t4-2012-2.pdf|tarea 4 del semestre Primavera de 2012]].
 ===== Servidor Multi-Clientes con Threads ===== ===== Servidor Multi-Clientes con Threads =====
  
Línea 581: Línea 579:
 </code> </code>
  
-=== Ejercicio ===+=== Ejercicios propuestos ===
  
   * Modifique el servidor de chat para que no reenvíe el mensaje al cliente que lo envía.   * Modifique el servidor de chat para que no reenvíe el mensaje al cliente que lo envía.
   * Modifique el cliente de chat para que agregue el nombre del usuario a todos los mensajes.   * Modifique el cliente de chat para que agregue el nombre del usuario a todos los mensajes.
-  * Estudie el código de serv-dict2.c correspondiente al ejercicio resuelto al comienzo de esta sección.  En esta versión, cuando un cliente consulta una llave inexistente, se bloquea hasta que se defina esa llava y por lo tanto satisface el enunciado.  En este caso hay que usar múltiples threads en el servidor. 
  
-=== Ejercicio resueltoservidor para un diccionario inter procesos ===+=== Ejercicios resueltos ===
  
-Estudie los programas serv-dict.c, serv-dict2.c y dict.c en [[http://users.dcc.uchile.cl/~lmateu/CC3301/download/serv-dict.tgz|este link]] en formato tar comprimido con gzip.  El programa serv-dict.c es una solución incompleta de la +  * Servidor para un diccionario inter procesos.  Estudie los programas serv-dict.c, serv-dict2.c y dict.c en [[http://users.dcc.uchile.cl/~lmateu/CC3301/download/serv-dict.tgz|este link]] en formato tar comprimido con gzip.  El programa serv-dict.c es una solución incompleta de la [[http://users.dcc.uchile.cl/~lmateu/CC3301/tareas/t4-2013-1.pdf|tarea 4 del semestre Otoño de 2013]].  Es incompleta porque si un cliente consulta una llave y la llave no está definida, el cliente no espera.  La solución completa es serv-dict2.c.  Además los comandos usados son d para definir (no def), q para consultar (no query) y e para eliminar
-[[http://users.dcc.uchile.cl/~lmateu/CC3301/tareas/t4-2013-1.pdf|tarea 4 del semestre Otoño de 2013]]. +  * Determinar si un número es primo buscando algún factor.  Estudie la [[http://users.dcc.uchile.cl/~lmateu/CC3301/download/c3-sol-2013-2.zip|solución]] del [[http://users.dcc.uchile.cl/~lmateu/CC3301/controles/c3-132.pdf|control 3 del semestre Primavera 2013]].  Pruebe las distintas implementaciones con números primos sacados de la [[http://en.wikipedia.org/wiki/List_of_prime_numbers|wikipedia]].
-Es incompleta porque si un cliente consulta una llave y la llave no está definida, el cliente no +
-espera.  La solución completa es serv-dict2.c.  Además los comandos usados son d para definir (no def), q para consultar (no query) y e para eliminar.+
 ===== Servidor Multi-cliente con select ===== ===== Servidor Multi-cliente con select =====
  
Línea 704: Línea 699:
 de chat con threads: nunca se bloquea para todos los clientes. de chat con threads: nunca se bloquea para todos los clientes.
  
-===== Proxy genérico ===== 
- 
-Se trata de escribir un programa que haga de "proxy" de un servidor: se trata de instalar un intermediario que simula ser un servidor, pero que en realidad "representa" a otro servidor que ahora está en otra máquina. Es como un "forwarder" que sirve para instalarlo si movemos un servidor de una máquina a otra y queremos que los clientes antiguos sigan funcionando, o para instalar en un computador que es accesible desde Internet para representar un servidor que está en un computador sin acceso a Internet (una intranet por ejemplo). La invocación de este proxy es: 
-<code> 
-% ./proxy port-in server port-out 
-</code> 
-Escucha en la máquina local conexiones que llegan a port-in, luego se conecta a (server, port-out) y luego envía y recibe todos los datos de ambos lados. Haremos dos versiones, una que crea dos procesos hijos (uno que copia en una 
-dirección del socket y otro que copia en la dirección opuesta) y otra con select que queda mejor. 
- 
-Solución con 2 hijos: 
-<code C> 
- #include <stdio.h> 
-#include <stdlib.h> 
-#include <signal.h> 
-#include <wait.h> 
-#include "jsocket.h" 
- 
-/* 
- * proxy: proxy multi-cliente usando procesos pesados 
- * Hacer version con select? 
- */ 
- 
-#define BUF_SIZE 200 
- 
-/* 
- * Esta es la forma mas simple de enterrar a los hijos sin complicarse l 
-a vida 
- */ 
-void child() { 
-    int status; 
- 
-    while(waitpid(-1, &status, WNOHANG)>0) 
- ; 
-} 
- 
-void die() { 
-    fprintf(stderr, "cliente desconectado\n"); 
-    exit(0); 
-} 
- 
-/* 
- * Este es el servidor y el codigo para un socket cliente ya conectado:  
- */ 
-void proxy(int s1, char *host, int portout) { 
-   int cnt, size = BUF_SIZE; 
-   char buf[BUF_SIZE]; 
-   int s2; 
-   int pid; 
- 
-   signal(SIGUSR1, die); 
- 
-   s2 = j_socket(); 
- 
-   if(j_connect(s2, host, portout) < 0) { 
- fprintf(stderr, "connection refused to %s/%d\n", host, portout); 
- exit(1); 
-   } 
-   fprintf(stderr, "cliente conectado\n"); 
-  
-   if((pid = fork()) < 0) { 
-    fprintf(stderr, "no pude fork\n"); 
- exit(1); 
-   } 
- 
-   if(pid == 0) { 
-    while((cnt=read(s1, buf, size)) > 0) 
-     if(write(s2, buf, cnt) < 0) break; 
- kill(getppid(), SIGUSR1); 
- exit(0); 
-   } else 
-    while((cnt=read(s2, buf, size)) > 0) 
-     if(write(s1, buf, cnt) < 0) break; 
- 
-    kill(pid, SIGKILL); 
-    fprintf(stderr, "cliente desconectado\n"); 
-} 
- 
-/* 
- * Este es el principal: solo acepta conexiones y crea a los hijos servi 
-dores 
- */ 
-main(int argc, char **argv) { 
-   int s, s2; 
-   int portin, portout; 
-   char *host; 
- 
-   if(argc != 4) { 
- fprintf(stderr, "Use: %s port-in host port-out\n", argv[0]); 
- exit(1); 
-   } 
- 
-   portin = atoi(argv[1]); 
-   host = argv[2]; 
-   portout = atoi(argv[3]); 
- 
-   signal(SIGCHLD, child); 
- 
-   s = j_socket(); 
- 
-   if(j_bind(s, portin) < 0) { 
- fprintf(stderr, "bind failed\n"); 
- exit(1); 
-   } 
- 
-   for(;;) { 
- s2 = j_accept(s); 
- if(fork() == 0) { /* Este es el hijo */ 
-     close(s); /* cerrar el socket que no voy a usar */ 
-     proxy(s2, host, portout); 
-     exit(0); 
- } else 
-     close(s2); /* cerrar el socket que no voy a usar */ 
-   } 
-} 
-</code> 
- 
-Y una mejor con select: 
-<code C> 
-#include <stdio.h> 
-#include <stdlib.h> 
-#include <signal.h> 
-#include <wait.h> 
-#include "jsocket.h" 
- 
-/* 
- * proxy: proxy multi-cliente usando procesos pesados 
- * version con select 
- */ 
- 
-#define BUF_SIZE 200 
- 
-/* 
- * Esta es la forma mas simple de enterrar a los hijos sin complicarse l 
-a vida 
- */ 
-void child() { 
-    int status; 
- 
-    while(waitpid(-1, &status, WNOHANG)>0) 
- ; 
-} 
- 
-/* 
- * Este es el servidor y el codigo para un socket cliente ya conectado:  
-s 
- */ 
-void proxy(int s1, char *host, int portout) { 
-   int cnt, size = BUF_SIZE; 
-   char buf[BUF_SIZE]; 
-   int s2; 
-   int pid; 
-   fd_set mask; 
- 
-   s2 = j_socket(); 
- 
-   if(j_connect(s2, host, portout) < 0) { 
- fprintf(stderr, "connection refused to %s/%d\n", host, portout); 
- exit(1); 
-   } 
-   fprintf(stderr, "cliente conectado\n"); 
-  
-/* 
-       int select(int numfds, fd_set *readfds, fd_set *writefds , 
-       fd_set *exceptfds, struct timeval * timeout); 
- 
-       FD_CLR(int fd, fd_set *set); 
-       FD_ISSET(int fd, fd_set *set); 
-       FD_SET(int fd, fd_set *set); 
-       FD_ZERO(fd_set * set); 
-*/ 
-    
-    
-    for(;;) { 
-        FD_ZERO(&mask); 
-        FD_SET(s1, &mask); FD_SET(s2, &mask); 
- select(getdtablesize(), &mask, NULL, NULL, NULL); 
- if(FD_ISSET(s1, &mask)) { 
-        cnt=read(s1, buf, size); 
-     if(cnt <= 0) { 
-    fprintf(stderr, "cliente desconectado\n"); 
- exit(0); 
-     } 
-     write(s2, buf, cnt); 
- } 
- if(FD_ISSET(s2, &mask)) { 
-        cnt=read(s2, buf, size); 
-     if(cnt <= 0) { 
-    fprintf(stderr, "cliente desconectado\n"); 
-  exit(0); 
-     } 
-     write(s1, buf, cnt); 
- } 
-    } 
-} 
- 
-/* 
- * Este es el principal: solo acepta conexiones y crea a los hijos servi 
-dores 
- */ 
-main(int argc, char **argv) { 
-   int s, s2; 
-   int portin, portout; 
-   char *host; 
- 
-   if(argc != 4) { 
- fprintf(stderr, "Use: %s port-in host port-out\n", argv[0]); 
- exit(1); 
-   } 
- 
-   portin = atoi(argv[1]); 
-   host = argv[2]; 
-   portout = atoi(argv[3]); 
- 
-   signal(SIGCHLD, child); 
- 
-   s = j_socket(); 
- 
-   if(j_bind(s, portin) < 0) { 
- fprintf(stderr, "bind failed\n"); 
- exit(1); 
-   } 
- 
-   for(;;) { 
- s2 = j_accept(s); 
- if(fork() == 0) { /* Este es el hijo */ 
-     close(s); /* cerrar el socket que no voy a usar */ 
-     proxy(s2, host, portout); 
-     exit(0); 
- } else 
-     close(s2); /* cerrar el socket que no voy a usar */ 
-   } 
-} 
-</code> 
- 
-=== El super demonio inetd === 
  
-Estudie [[http://users.dcc.uchile.cl/~lmateu/CC3301/apuntes/Sockets/|el super demonio inetd]] que aparece en los apuntes de Patricio Poblete. 
  
sockets-jo.1414597286.txt.gz · Última modificación: 2014/10/29 15:41 por lmateu