sockets-jo
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
| sockets-jo [2014/10/29 15:33] – [Servidor Multi-Clientes con Fork] lmateu | sockets-jo [2018/08/16 13:04] (actual) – [Proxy genérico] lmateu | ||
|---|---|---|---|
| Línea 134: | Línea 134: | ||
| #include < | #include < | ||
| #include < | #include < | ||
| + | #include < | ||
| + | |||
| #include " | #include " | ||
| - | |||
| - | /* | ||
| - | * client_echo2: | ||
| - | * que recibe de vuelta lo envía a su salida estándar. | ||
| - | */ | ||
| #define BUF_SIZE 1024 | #define BUF_SIZE 1024 | ||
| int main() { | int main() { | ||
| - | | + | int s; |
| - | int cnt, cnt2; | + | int rc; |
| - | char buf[BUF_SIZE]; | + | int cnt, cnt2; |
| + | | ||
| - | | + | s = j_socket(); |
| - | if (j_connect(s, | + | |
| - | | + | if (rc<0) { |
| - | exit(1); | + | |
| - | } | + | exit(1); |
| + | | ||
| - | | + | while ((cnt=read(0, |
| - | if (write(s, buf, cnt) != cnt) { | + | if(write(s, buf, cnt) != cnt) { |
| - | | + | perror(" |
| - | exit(1); | + | |
| - | } | + | } |
| - | while (cnt > 0 && (cnt2=read(s, | + | while(cnt > 0) { |
| - | write(1, buf, cnt2); | + | cnt2=read(s, |
| - | cnt -= cnt2; | + | if (cnt2<=0) { |
| - | } | + | if (cnt2==0) |
| - | } | + | |
| + | | ||
| + | | ||
| + | | ||
| + | } | ||
| + | | ||
| + | write(1, buf, cnt2); | ||
| + | | ||
| + | } | ||
| + | | ||
| - | | + | return 0; |
| } | } | ||
| </ | </ | ||
| Línea 293: | Línea 301: | ||
| while (waitpid(-1, | while (waitpid(-1, | ||
| - | chld_cnt--; | + | chld_cnt--; |
| signal(SIGCHLD, | signal(SIGCHLD, | ||
| } | } | ||
| Línea 346: | Línea 354: | ||
| continue; | continue; | ||
| } | } | ||
| - | chld_cnt++; | + | chld_cnt++; |
| if (fork() == 0) { /* Este es el hijo */ | if (fork() == 0) { /* Este es el hijo */ | ||
| close(s); /* cerrar el socket que no voy a usar */ | close(s); /* cerrar el socket que no voy a usar */ | ||
| Línea 365: | Línea 373: | ||
| </ | </ | ||
| - | === Ejercicio resuelto: | + | === Ejercicio resuelto: |
| - | + | ||
| - | Estudie los programas servidor-cat.c y cat-remoto.c en [[http:// | + | |
| - | [[http:// | + | |
| + | Estudie los programas servidor-cat.c y cat-remoto.c en [[http:// | ||
| ===== Servidor Multi-Clientes con Threads ===== | ===== Servidor Multi-Clientes con Threads ===== | ||
| Línea 573: | Línea 579: | ||
| </ | </ | ||
| - | === 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. | ||
| - | === Ejercicio resuelto: servidor para un diccionario inter procesos | + | === Ejercicios resueltos: === |
| - | Estudie los programas serv-dict.c, | + | * Servidor para un diccionario inter procesos. |
| - | [[http:// | + | * Determinar si un número es primo buscando algún factor. |
| - | Es incompleta porque si un cliente consulta una llave y la llave no está definida, el cliente no | + | |
| - | espera. | + | |
| ===== Servidor Multi-cliente con select ===== | ===== Servidor Multi-cliente con select ===== | ||
| Línea 696: | 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 port-in server port-out | ||
| - | </ | ||
| - | 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 < | ||
| - | #include < | ||
| - | #include < | ||
| - | #include " | ||
| - | |||
| - | /* | ||
| - | * 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, | ||
| - | ; | ||
| - | } | ||
| - | |||
| - | void die() { | ||
| - | fprintf(stderr, | ||
| - | 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; | ||
| - | |||
| - | | ||
| - | |||
| - | s2 = j_socket(); | ||
| - | |||
| - | | ||
| - | fprintf(stderr, | ||
| - | exit(1); | ||
| - | } | ||
| - | | ||
| - | |||
| - | | ||
| - | fprintf(stderr, | ||
| - | exit(1); | ||
| - | } | ||
| - | |||
| - | | ||
| - | while((cnt=read(s1, | ||
| - | if(write(s2, | ||
| - | kill(getppid(), | ||
| - | exit(0); | ||
| - | } else | ||
| - | while((cnt=read(s2, | ||
| - | if(write(s1, | ||
| - | |||
| - | kill(pid, SIGKILL); | ||
| - | fprintf(stderr, | ||
| - | } | ||
| - | |||
| - | /* | ||
| - | * 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; | ||
| - | |||
| - | | ||
| - | fprintf(stderr, | ||
| - | exit(1); | ||
| - | } | ||
| - | |||
| - | | ||
| - | host = argv[2]; | ||
| - | | ||
| - | |||
| - | | ||
| - | |||
| - | s = j_socket(); | ||
| - | |||
| - | | ||
| - | fprintf(stderr, | ||
| - | exit(1); | ||
| - | } | ||
| - | |||
| - | | ||
| - | 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 */ | ||
| - | } | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | Y una mejor con select: | ||
| - | <code C> | ||
| - | #include < | ||
| - | #include < | ||
| - | #include < | ||
| - | #include < | ||
| - | #include " | ||
| - | |||
| - | /* | ||
| - | * 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, | ||
| - | ; | ||
| - | } | ||
| - | |||
| - | /* | ||
| - | * 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; | ||
| - | | ||
| - | |||
| - | s2 = j_socket(); | ||
| - | |||
| - | | ||
| - | fprintf(stderr, | ||
| - | exit(1); | ||
| - | } | ||
| - | | ||
| - | |||
| - | /* | ||
| - | int select(int numfds, fd_set *readfds, fd_set *writefds , | ||
| - | | ||
| - | |||
| - | | ||
| - | | ||
| - | | ||
| - | | ||
| - | */ | ||
| - | |||
| - | |||
| - | for(;;) { | ||
| - | FD_ZERO(& | ||
| - | FD_SET(s1, &mask); FD_SET(s2, &mask); | ||
| - | select(getdtablesize(), | ||
| - | if(FD_ISSET(s1, | ||
| - | cnt=read(s1, | ||
| - | if(cnt <= 0) { | ||
| - | fprintf(stderr, | ||
| - | exit(0); | ||
| - | } | ||
| - | write(s2, buf, cnt); | ||
| - | } | ||
| - | if(FD_ISSET(s2, | ||
| - | cnt=read(s2, | ||
| - | if(cnt <= 0) { | ||
| - | fprintf(stderr, | ||
| - | | ||
| - | } | ||
| - | 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; | ||
| - | |||
| - | | ||
| - | fprintf(stderr, | ||
| - | exit(1); | ||
| - | } | ||
| - | |||
| - | | ||
| - | host = argv[2]; | ||
| - | | ||
| - | |||
| - | | ||
| - | |||
| - | s = j_socket(); | ||
| - | |||
| - | | ||
| - | fprintf(stderr, | ||
| - | exit(1); | ||
| - | } | ||
| - | |||
| - | | ||
| - | 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 */ | ||
| - | } | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | === El super demonio inetd === | ||
| - | Estudie [[http:// | ||
sockets-jo.1414596782.txt.gz · Última modificación: por lmateu
