Facultad de Ingeniería 66.48 – Seminario de Redes de Computadoras Trabajo Práctico Nº: 4 Tema: Sockets TCP/UDP 66.48 – Seminario de Redes de Computadoras (2º cuatrimestre 2007) Docentes: Ing. Marcelo Utard; Ing. Pablo Ronco Alumnos: Bianchi Mariano Soto Fernando Ricci Alberto 79854 74824 78757 TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras Introducción: ¿Qué es un Socket? Los sockets son una abstracción que provee un sistema operativo para realizar comunicaciones entre procesos en forma transparente. Como definición informal podrían definirse como una manera de que dos programas (procesos) se comuniquen entre si usando descriptores de archivos Unix estándar. Lo que esto quiere decir es que cuando un programa Unix realiza cualquier tipo de E/S, lo hacen leyendo o escribiendo a un descriptor de archivo. Un descriptor de archivo es simplemente un número entero asociado a un archivo abierto. Pero ese archivo puede ser una conexión de red, un FIFO, un terminal, un archivo real en el disco, u otra cosa. Así que cuando se desea comunicar dos procesos por medio de una red puede hacerse a través de un descriptor de archivo. Resumiendo: • • Un socket es una interfaz de entrada-salida de datos que permite la intercomunicación entre procesos. Los procesos pueden estar ejecutándose en el mismo o en distintos sistemas, unidos mediante una red. Dominios de comunicación Los sockets se crean dentro de un dominio de comunicación, igual que un archivo se crea dentro de un filesystem. El dominio de comunicación nos dice donde se encuentran los procesos que se van a intercomunicar. Si los procesos están en el mismo sistema, el dominio de comunicación será AF_UNIX, si los procesos están en distintos sistemas y estos se hallan unidos mediante una red TCP/IP, el dominio de comunicación será AF_INET. Cabe aclarar que existen otros dominios de comunicación. Los sockets no se han diseñado solamente para TCP/IP. La idea original fue que se usase la misma interfaz también para distintas familias de protocolos. Tipos de Sockets Hay varios tipos de sockets, están las direcciones de Internet DARPA (sockets de Internet), nombres de ruta en un nodo local (sockets de Unix), direcciones CCITT X.25 (sockets X.25). Este trabajo está basado en el primero: Sockets de Internet pertenecientes al dominio AF_INET. 2|P ági na TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras Los dos tipos de sockets de Internet más usados son los “Stream Sockets” (Sockets de Flujo) y “Datagram Sockets” (Sockets de Datagramas) a los que nos referiremos como “SOCK_STREAM” y “SOCK_DGRAM”, respectivamente. Los SOCK_DGRAM son a veces llamados “sockets sin conexión”. Tipos de sockets en el dominio AF_INET • • • Sockets Stream. Sockets Datagram. Sockets Raw. Sockets Stream : Son los más utilizados, hacen uso del protocolo TCP el cual nos provee un flujo de datos bidireccional, secuenciado, sin duplicación de paquetes y libre de errores. Sockets Datagram: Hacen uso del protocolo UDP, el cual nos provee un flujo de datos bidireccional, pero los paquetes pueden llegar fuera de secuencia o pueden no llegar. Por lo tanto el proceso que recibe los datos debe realizar reordenamiento, eliminar duplicados y asegurar la confiabilidad. Se llaman también sockets sin conexión, porque no hay que mantener una conexión activa, como en el caso de sockets stream. Son utilizados para transferencia de información paquete por paquete. Como Ejemplos de aplicación de estos son: dns, tftp, bootp, etc. Sockets raw: No son para el usuario más común, son provistos principalmente para aquellos interesados en desarrollar nuevos protocolos de comunicación o para hacer uso de facilidades ocultas de un protocolo existente. Estructuras de Datos usadas La estructura general para el almacenamiento de direcciones de sockets es la estructura SOCKADDR: struct sockaddr { unsigned short sa_family; // familia de direcciones, AF_xxx char sa_data[14]; // 14 bytes de la dirección del protocolo }; 3|P ági na TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras Esta estructura solo posee un campo de definición del tipo de socket y espacio suficiente para el almacenamiento de cualquier dirección conocida. En nuestro caso solo utilizaremos sockets de internet, por lo que resulta conveniente la utilización de la estructura SOCKADDR_IN que en realidad es una redefinición de la anterior. struct sockaddr_in { short int sin_family; // Dominio de la dirección. unsigned short int sin_port; // Número de Puerto. struct in_addr sin_addr; // Direccion de Internet. unsigned char sin_zero[8]; // Compatibilidad. }; Esta estructura facilita la referencia a cada elemento de dirección de socket, como son la IP y el puerto. Notar que sin_zero es incluido para acomodar la estructura al largo de STRUCT SOCKADDR que es una estructura anteriormente usada y por ende debe ser establecido a todos los ceros (zeros) con la función memset(). Además un puntero a STRUCT SOCKADDR_IN puede lanzar un puntero a STRUCT SOCKADDR y vise-versa. Así que si socket() necesita un STRUCT SOCKADDR*, se puede aún usar STRUCT SOCKADDR_ IN* usando un casting del tipo de datos. En esta estructura, SIN_PORT y SIN_ADDR deben ser Network Byte Order (NBO). Luego la estructura IN_ADRR se define como: struct in_addr { unsigned long s_addr; // Direccion IP (4 Bytes) }; Por lo tanto si definimos: struct sockaddr_in myAdd; 4|P ági na TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras myAdd.sin_addr.s_addr haría referencia a una dirección IP de 4 bytes (en NBO). Conversión de Órdenes – NBO/HBO HBO - Host Byte Order NBO – Network Byte Order Ambos términos se refieren a la forma de almacenar los datos en la memoria de host o al orden en que los datos son emitidos al medio de comunicación (Big Endian o Little Endian). Existen funciones de C que se encargan de ajustar las diferencias que pudieran existir entre los ordenes de los bytes en el host y la red. Hay dos tipos que se pueden convertir: short (2 bytes) y long (4 bytes): htons() “Host to network Short” htonl() “Host to network Long” ntohs() “Network to Host Short” ntohl() “Network to Host Long” SIN_ADDR y SIN_PORT necesitan estar en NBO en STRUCT SOCKADDR_IN, pero SIN_FAMILY no. Esto se debe a que SIN_ADDR y SIN_PORT son encapsulados en el paquete en las capas IP y UDP, respectivamente (entonces deben estar en el orden que la red los espera); mientras que el campo SIN_FAMILY es sólo usado por el kernel para determinar qué tipo de dirección contiene la estructura, así que debe estar en HBO. Es importante recordar poner los bytes en NBO antes de ponerlos en la Red ya que, entre otras cosas, asegura la portabilidad del programa creado bajo un sistema operativo dado. Manejo de direcciones IP Existen funciones que permiten el manejo de direcciones IP, la función inet_addr(), convierte una dirección IP dada en la notación de cifras y puntos en un unsigned long. La asignación se puede hacer así: ina.sin_addr.s_addr = inet_addr("172.31.1.7"); 5|P ági na TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras Es de notar que inet_addr() ya devuelve la dirección según la Ordenación de bytes de la red por lo que no es necesario llamar a htonl(). Llamadas al sistema (System Calls) Los sistemas operativos tradicionalmente proporcionan una interfase para que las aplicaciones de espacio de usuario puedan comunicarse con el hardware. Esta interfase son las system calls, conocidas en Linux simplemente como syscalls. Mediante estas llamadas, las aplicaciones podrán pedir al sistema operativo que realice tareas en su nombre. Por ejemplo, la función open() emitida por un proceso de usuario, estará indicando al kernel que abra algún archivo, el kernel que es el único con potestad para acceder al hardware (en este caso el disco), realizará la apertura del archivo que la aplicación le haya indicado en sus parámetros, es decir, el kernel se ejecutará en nombre del proceso de usuario, realizando la tarea que le ha sido pedida. En realidad, las llamadas al sistema son casi el único punto de entrada que tienen los procesos de espacio de usuario al kernel. Es el principal mecanismo de comunicación de las aplicaciones con el kernel. El puente AP I / Syscall Para que nuestra aplicación de espacio de usuario pueda emitir una syscall, es necesario poder realizar la llamada mediante un API que alguien nos proporcione. Este API lo proporciona la librería estándar de C de nuestro sistema. En la siguiente figura podemos ver la relación existente entre las aplicaciones, la librería de C y la llamada al kernel para la función “printf()” en un sistema operativo Linux. Las llamadas al sistema nos permiten el establecimiento de un socket en cada uno de los procesos y la comunicación transparente entre ellos a través de la red que comparten. socket() Para obtener el descriptor antes mencionado se debe una llamada a la rutina de sistema (syscall) socket(). Ésta devuelve el descriptor del socket con el cual es posible establecer comunicación entre procesos usando las funciones send() y recv(). Dado que es un descriptor también se 6|P ági na TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras pueden usar las funciones read() y write() para comunicarse a través del socket pero send() y recv() ofrecen un mejor control sobre transmisión de datos. La sintaxis de esta función es: #include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol); Los argumentos de la función socket() son: • • • domain es un "AF_INET", igual que en la estructura struct sochaddr_in de arriba. type le dice al kernel qué tipo de socket es (SOCK_STREAM o SOCK_DGRAM) protocol se le asigna un "0" para que socket() elija el protocolo correcto en función del tipo(type). Hay muchos más dominios (domain) y tipos (type) de los que se han listado. Además, hay una manera mejor de obtener el protocolo (protocol). La función socket() sólo devuelve un descriptor de socket que puede usarse en posteriores llamadas al sistema, o -1 en caso de error. bind() Una vez que se tiene el socket, se lo puede asociar con algún puerto de la máquina. (Esto es lo que comúnmente se hace si se va a escuchar [listen()] a la espera de conexiones entrantes sobre un puerto específico). El kernel usa el número de puerto para asociar los paquetes entrantes con un descriptor de socket de un cierto proceso. Si solamente se va a hacer un connect() esto no es necesario. Sinopsis de llamada al sistema bind() : #include <sys/types.h> #include <sys/socket.h> int bind(int sockfd, struct sockaddr *my_addr, int addrlen); Los argumentos de la función bind() son: sockfd es el descriptor de archivo de socket que devolvió socket(). 7|P ági na TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras my_addr es un puntero a una estructura struct sockaddr que contiene información acerca de la dirección propia, (puerto y dirección IP). addrlen se puede asignar a sizeof(struct sockaddr) . bind() devuelve -1 en caso de error No es recomendable usar números de puerto demasiado pequeños. Todos los puertos por debajo del 1024 están RESERVADOS(salvo para el superusuario). Se puede usar cualquier número de puerto por encima del 1024, hasta el 65535(siempre y cuando no lo esté usando otro programa). Puede ocurrir que al volver a ejecutar bind() en un servidor se obtenga el error "Address already in use". Esto significa que parte de un socket que estuvo conectado, está todavía colgando en el núcleo y está bloqueando el puerto. Se puede esperar a que se libere (alrededor de un minuto) o añadir código permitiendo reutilizar el puerto. connect() Se utiliza para conectarse a una máquina remota. Sinopsis de llamada al sistema connect() : #include <sys/types.h> #include <sys/socket.h> int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); Los argumentos de la función connect() son: sockfd es el descriptor de archivo de socket, como lo devolvió la llamada a socket() serv_addr es una estructura struct sockaddr que contiene el puerto y la dirección IP de destino addrlen se le puede asignar el valor sizeof(structsockaddr). Sólo importa el puerto remoto. El núcleo elegirá un puerto local connect() devolverá -1 en caso de error. 8|P ági na TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras listen() y accept() Cuando se desea realizar un servidor, se quiere esperar a que lleguen conexiones entrantes y gestionarlas de alguna manera. El proceso consta de dos pasos: en primer lugar se escucha (listen() ) y después se acepta ( accept() ). listen() La llamada listen() tiene la siguiente forma: int listen(int sockfd, int backlog); • • sockfd es un descriptor de archivo de socket backlog es el número de conexiones permitidas en la cola de entrada. Las conexiones entrantes van a esperar en esta cola hasta que se las acepte (accept() ) y éste es el límite de conexiones que puede haber en cola. Se necesita llamar a bind() antes de poder llamar a listen(), de lo contrario el kernel dejará escuchando al programa en un puerto aleatorio. Por lo tanto para estar a la espera de conexiones entrantes, la secuencia de llamadas que corresponde hacer es: socket(); bind(); listen(); accept() La llamada al sistema accept() permite aceptar una conexión entrante a un puerto en el que estamos escuchando, cuando un host remoto intente establecer una conexión mediante connect(). Cuando el host remoto ejecuta connect su conexión pasará a cola, esperando a ser aceptada. Cuando se llama a accept() esta obtiene la primera conexión pendiente de la cola y devolverá un socket nuevo para usar en esta nueva conexión. El original estará todavía escuchando en el puerto, y el de nueva creación estará listo para enviar (send()) y recibir (recv()). 9|P ági na TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras La llamada es como sigue: #include <sys/socket.h> int accept(int sockfd, void *addr, int *addrlen); • • • sockfd es el descriptor de archivo donde se está escuchando (listen()) addr es un puntero a una estructura struct sockaddr_in local, donde se guardará la información de la conexión entrante (con la cual se puede averiguar que máquina está llamando, y desde qué puerto) addrlen es un puntero a una variable local int a la que se debe asignar el valor de sizeof(struct sockaddr_in) . send() y recv() Estas dos funciones sirven para comunicarse a través de sockets de flujo o sockets de datagramas conectados. La llamada al sistema send() es: int send(int sockfd, const void *msg, int len, int flags); • • • • sockfd es el descriptor de socket al que se quiere enviar datos (puede ser el devuelto por socket(), o bien el devuelto por accept().) msg es un puntero a los datos a enviar len es la longitud de esos datos en bytes flags lleva normalmente el valor 0, y sirve para establecer opciones. La llamada send() devuelve el número de bytes que se enviaron en realidad, lo que sirve para detectar errores. La llamada al sistema recv() es similar en muchos aspectos: int recv(int sockfd, void *buf, int len, unsigned int flags); 10 | P á g i n a TP4 – Sockets TCP/UDP • • • • 66.48 - Seminario de Redes de Computadoras sockfd es el descriptor del archivo del que se va a leer buff es el buffer donde se va a depositar la información leída len es la longitud máxima del buffer flags nuevamente son indicaciones Como antes, recv() devuelve el número de bytes que se leyeron en realidad, o -1 en caso de error (y establece errno apropiadamente). Si recv() devuelve 0, significa que la máquina remota ha cerrado su conexión. sendto() y recvfrom() Estas funciones sirven para el envío y recepción de datagramas sobre sockets UDP. Puesto que los sockets de datagramas no están conectados a una máquina remota, solo se necesita pasarle a las llamadas la dirección de destino: int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen); Como se puede ver, esta llamada es básicamente la misma que send()añadiendo dos items más de información: • • to es un puntero a una estructura struct sockaddr, que contiene la dirección IP y el puerto de destino tolen es la longitud de to, se le asigna el valor sizeof(struct sockaddr). Lo mismo que send(), sendto() devuelve el número de bytes que realmente se enviaron (que, igual que antes, podrían ser menos de los que se enviaron) La misma semejanza presentan recv() y recvfrom(). La sinopsis de recvfrom() es: int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen); Los campos from y fromlen son similares a to y tolen de sendto. 11 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras close() y shutdown() Se utilizan para cerrar la conexión del descriptor de socket. Sólo hay que usar la función close() que cierra descriptores de archivo: close(sockfd); Esto impedirá más lecturas y escrituras al socket. Cualquiera que intente leer o escribir sobre el socket desde el extremo remoto recibirá un error. Si se desea un poco más de control sobre cómo se cierra el socket se puede usar la función shutdown() que permite cortar la comunicación en un sentido, o en los dos (como lo hace close()). Sinopsis de la llamada al sistema shutdown: int shutdown(int sockfd, int how); sockfd es el descriptor de socket que se desea desconectar, y how puede tener uno de los siguientes valores: 0 -- No se permite recibir más datos 1 -- No se permite enviar más datos 2 -- No se permite enviar ni recibir más datos (similar a close()) shutdown() devuelve 0 si tiene éxito, y -1 en caso de error Si se usa shutdown() en un datagram socket, simplemente inhabilitará el socket para posteriores llamadas a send() y recv() shutdown() no cierra realmente el descriptor de archivo, sólo cambia sus condiciones de uso. Para liberar un descriptor de socket es necesario usar close(). Particularidades en la portabilidad de código Unix a Windows: Para que una aplicación creada para Unix corra bajo un sistema operativo Windows se debe: 1- Incluir la librería winsock 2- Hacer una llamada a WSAStartup() antes de hacer algo con la Librería de Sockets. El código para hacer esto: 12 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras #include <winsock.h> { WSAData wsaData; If (WSAStartup{MAKEWORD(1, 1), &wsaData} != 0) { Fprintf(stderr, “WSAStartup failed.\n”); Exit(1); } WSAStarup: Se debe llamar a esta función antes de llamar a cualquiera otra de winsock. Nos permite especificar que versión de la API de Windows socket va a necesitar nuestro programa. Se establece una negociación entre la aplicación y Winsock.dll WSCleanup() termina sesion desde los DLL subyacentes de winsock. 13 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras Modelo Cliente-Servidor Este es un mundo cliente-servidor. Casi cualquier cosa en la red tiene que ver con procesos clientes que dialogan con procesos servidores y viceversa. Consideremos telnet, por ejemplo. Cuando nos conectamos al puerto 23 de una máquina remota mediante telnet (el cliente) un programa de aquella máquina (llamado telnetd, el servidor) despierta a la vida. Gestiona la conexión telnet entrante, presenta una pantalla de login, etc. Figura 1. Interacción Cliente-Servidor. El intercambio de información entre cliente y servidor se resume en la Figura 1. En ella se puede observar que el par cliente-servidor pueden hablar SOCK_STREAM , SOCK_DGRAM o cualquier otra cosa (siempre y cuando los dos hablen lo mismo). Algunos buenos ejemplos de parejas cliente-servidor son telnet/telnetd , ftp/ftpd, o bootp/bootpd. Cada vez que usamos ftp, hay un programa remoto, ftpd, que nos sirve. Con frecuencia, solamente habrá un servidor en una máquina determinada, que atenderá a múltiples clientes usando fork(). El funcionamiento básico es: el servidor espera una conexión, la acepta (accept()) y usa fork() para obtener un proceso hijo que la atienda. Eso es lo que hace nuestro servidor de ejemplo en la siguiente sección. En realidad no hay demasiado que contar aquí, así que sólo presentaré un par de programas de ejemplo: talker.c y listener.c. listener se sienta a esperar en la máquina hasta que llega un paquete al puerto 4950. talker envía un paquete a ese puerto en la máquina indicada que contiene lo que el usuario haya escrito en la línea de comandos. Código fuente del servidor “listener.c”: /* ** listener.c -- Ejemplo de servidor de sockets de datagramas */ #include #include #include #include #include #include <stdio.h> <stdlib.h> <unistd.h> <errno.h> <string.h> <sys/types.h> 14 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define MYPORT 4950 // puerto al que conectarán los clientes #define MAXBUFLEN 100 int main(void) { int sockfd; struct sockaddr_in my_addr; // información sobre mi dirección struct sockaddr_in their_addr; // información sobre la dirección del cliente int addr_len, numbytes; char buf[MAXBUFLEN]; if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket"); exit(1); } my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT); my_addr.sin_addr.s_addr = INADDR_ANY; memset(&(my_addr.sin_zero), '\0', 8); // // // // Ordenación de bytes de máquina short, Ordenación de bytes de la red rellenar con mi dirección IP poner a cero el resto de la estructura if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } addr_len = sizeof(struct sockaddr); if ((numbytes=recvfrom(sockfd,buf, MAXBUFLEN-1, 0, (struct sockaddr *)&their_addr, &addr_len)) == -1) { perror("recvfrom"); exit(1); } printf("got packet from %s\n",inet_ntoa(their_addr.sin_addr)); printf("packet is %d bytes long\n",numbytes); buf[numbytes] = '\0'; printf("packet contains \"%s\"\n",buf); close(sockfd); return 0; } Observar que en nuestra llamada a socket() finalmente estamos usando SOCK_DGRAM. Observa también que no hay necesidad de escuchar (listen()) o aceptar (accept()). ¡Esa es una de las ventajas de usar sockets de datagramas sin conexión! A continuación el código fuente del cliente talker.c 15 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras /* ** talker.c -- ejemplo de cliente de datagramas */ #include #include #include #include #include #include #include #include #include #include <stdio.h> <stdlib.h> <unistd.h> <errno.h> <string.h> <sys/types.h> <sys/socket.h> <netinet/in.h> <arpa/inet.h> <netdb.h> #define MYPORT 4950 // puerto donde vamos a conectarnos int main(int argc, char *argv[]) { int sockfd; struct sockaddr_in their_addr; // información sobre la dirección del servidor struct hostent *he; int numbytes; if (argc != 3) { fprintf(stderr,"usage: talker hostname message\n"); exit(1); } if ((he=gethostbyname(argv[1])) == NULL) { //obtener información de máquina perror("gethostbyname"); exit(1); } if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket"); exit(1); } their_addr.sin_family = AF_INET; // Ordenación de bytes de máquina their_addr.sin_port = htons(MYPORT); // short, Ordenación de bytes de la red their_addr.sin_addr = *((struct in_addr *)he->h_addr); memset(&(their_addr.sin_zero), '\0', 8); // poner a cero el resto de la estructura if ((numbytes=sendto(sockfd, argv[2], strlen(argv[2]), 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) { perror("sendto"); exit(1); } printf("sent %d bytes to %s\n", numbytes, inet_ntoa(their_addr.sin_addr)); close(sockfd); return 0; } 16 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras Para compilar utilizamos el comando gcc listener.c utilizando un sistema operativo Linux CentOS 5. Esto genera un archivo a.out el cual lo renombramos a listener. Procedimos de manera análoga para el cliente (talker). ¡Y esto es todo! Ejecutamos listener (./listener) en una máquina y luego llama a talker en otra. Para terminar, cabe hacer la siguiente aclaración. Supongamos que talker llama a connect() e indica la dirección de listener. A partir de ese momento, talker solamente puede enviar a y recibir de la dirección especificada en connect(). Por ese motivo no tienes que usar sendto() y recvfrom(); tienes que usar simplemente send() y recv(). A continuación se muestra la captura del paquete UDP: 17 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras El escenario es muy simple: Hub Listener Talker 172.31.1.7 172.31.1.23 Para conseguir dicha captura se ejecutó el comando ./listener desde una terminal de la máquina cuya dirección IP es 172.31.1.7 y luego se ejecuta el comando ./talker 172.31.1.7 hola_mundo desde la PC “Talker”. La captura se hizo con el software Wireshark desde la PC Listener. 18 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras Cliente Servidor en TCP El cliente debe ser ejecutado de manera que pase como argumento la direccion destino y un numero entero cualquiera. Ejemplo ./cliente localhost 123. El cliente se contactara con el destino y le pasara ese numero. El servidor que previamente ejecute como ./servidor recibira ese numero y le devolvera al cliente si es un numero par o impar. Código fuente del servidor “servidor.c” TCP: /* Nombre Archivo: servidor.c Archivos relacionados: cliente_tcp.c Fecha: Enero 2008 Compilacion: gcc -Wall servidor_tcp.c -o servidor_tcp Ejecucion: ./servidor_tcp Sistema que indica si un numero es par o impar. Sistema basado en sockets tipo internet en modo conexion. El servidor sigue una estrategia servidor padre. El padre imprime el identificador del proceso que escucha en el puerto y lo identificadores de los procesos que proporcionan el servicio. */ #include #include #include #include #include #include #include #include <stdlib.h> <stdio.h> <unistd.h> <signal.h> <sys/types.h> <sys/socket.h> <netinet/in.h> <netdb.h> #define PUERTO 12345 /* numero puerto arbitrario */ char resp; /* para mandar al cliente */ char *mensaje; int pet; /* para guardar lo recibido por el cliente */ int sd, sd2; /* descriptores de sockets */ int addrlen; /* lomgitud direcciones */ struct sockaddr_in server, cliente;/* direcciones sockets servidor y cliente */ /* procedimiento de aborte del servidor, si llega una senal SIGINT */ /* ( <ctrl> <c> ) se cierra el socket y se aborta el programa */ void aborta() { printf("....abortando el proceso servidor \n"); close(sd); 19 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras close(sd2); exit(1); } /* ---------------- FUNCION MAIN -------------------------------------*/ int main() { /* activando la senal SIGINT */ signal(SIGINT, aborta); /* obtencion de un socket tipo internet */ if ( (sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } /* asignar direcciones en la estructura de direcciones */ server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; /* INADDR_ANY=0x000000 = yo mismo */ server.sin_port = htons(PUERTO); /* convirtiendo a formato red */ /* asociando del socket al numero de puerto */ if ( bind(sd, (struct sockaddr *)&server, sizeof(server)) == -1) { perror("bind"); exit(1); } /* ponerse a escuchar a traves del socket */ if (listen(sd, 5) == -1) { perror("listen"); exit(1); } /* imprimiendo id del proceso padre que espera conexiones */ printf("\n"); printf("\n"); printf("======================================================.\n"); printf("Iniciando Servidor_tcp ....<Control>+<C> para terminar.\n"); printf("======================================================.\n"); printf("Proceso padre %d escuchando en puerto %d \n",getpid(), PUERTO); printf("\n"); /* se entra al ciclo de escucha y peticion */ printf ("Esperando que un cliente solicite un servicio\n"); while(1) { /* esperando que un cliente solicite un servicio */ /* sd2:descriptor para hablar con el cliente. El sd corresponde al servicio y solo sirve para encolar a los clientes. En la estructura cliente se cargaran los datos del cliente que inicia la conexion */ addrlen = sizeof(cliente); /* necesario para la funcion accept */ 20 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras if ( (sd2 = accept(sd, (struct sockaddr *)&cliente, &addrlen)) == -1) { perror("accept"); exit(1); } /* se crea un hijo para atender la conexion */ if ( fork() == 0) { /* tomar un mensaje del cliente en pet se guardara la informacion recibida; en este caso pet sera un int donde guardamos el puerto recibido */ if ( recv(sd2, &pet, sizeof(pet), 0) == -1) { perror("recv"); exit(1); } /* imprimiendo el id del proceso que proporcioan el servicio */ printf("\tProceso %d atendiendo el servicio \n",getpid()); /* proporcionando el servicio */ if ((pet % 2) == 0) resp='p'; else resp='i'; /* enviando la respuesta del servicio */ if ( send(sd2, &resp, sizeof(resp), 0) == -1) { perror("send"); exit(1); } /* cerrando el canal privado de comunicacion */ close(sd2); /* termina ejecucion proceso hijo */ exit(0); } } /* cerrando el canal de conexion */ close(sd); /* adios, recordemos que el main es una funcion */ return 0; } Código fuente del cliente “cliente.c” TCP: /* Nombre Archivo: cliente_tcp.c Archivos relacionados: servidor_tcp.c Fecha: Enero 2008 Compilacion: gcc -Wall cliente_tcp.c -o cliente_tcp Ejecucion: cliente_tcp <host> <numero> Ejemplo: ./cliente_tcp localhost 12345 Sistema que indica si un numero es par o impar. Sistema basado en sockets tipo internet en modo conexion. */ 21 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras #include #include #include #include #include #include #include <stdlib.h> <stdio.h> <unistd.h> <sys/types.h> <sys/socket.h> <netinet/in.h> <netdb.h> #define PUERTO 12345 /* numero puerto arbitrario */ int main(int argc, char *argv[]) { char resp; int pet; int sd; struct hostent *hp; struct sockaddr_in pin; char *host; /* parametro entrada */ /* parametro de salida */ /* descriptor de socket */ /* estructura del host */ /* direcciones socket */ /* nombre del host */ /* verificando el paso de parametros */ if ( argc != 3) { fprintf(stderr,"uso: %s <host> <numero> \n",argv[0]); fprintf(stderr,"Ejemplo:\n"); fprintf(stderr," ./cliente localhost 123 \n"); exit(1); } /* tomando el nombre del host de los argumentos de la linea de comandos */ host = argv[1]; /* encontrando todo lo referente acerca de la maquina host */ if ( (hp = gethostbyname(host)) == 0) { perror("gethosbyname"); exit(1); } /* llenar la estructura de direcciones con la informacion del host */ pin.sin_family = AF_INET; pin.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr))->s_addr; pin.sin_port = htons(PUERTO); /* obtencion de un socket tipo internet */ if ( (sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } /* conectandose al PUERTO en el HOST */ if ( connect(sd, (struct sockaddr *)&pin, sizeof(pin)) == -1) { perror("connect"); exit(1); } /* enviar mensaje al PUERTO del servidor en la maquina HOST */ pet = atoi(argv[2]); /*cargo en pet el parametro pasado a la entrada*/ if ( send(sd, &pet, sizeof(pet), 0) == -1 ) { perror("send"); exit(1); } 22 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras /* esperar por la respuesta */ if ( recv(sd, &resp, sizeof(resp), 0) == -1 ) { perror("recv"); exit(1); } /* imprimir los resultados */ printf("El numero %d es ",pet ); if (resp == 'i') printf("impar \n"); else printf("par \n"); /* cerrando el socket */ close(sd); /* adios, recordemos que main es una funcion */ return 0; } 23 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras A continuación se muestra las capturas hechas con el Wireshark: No. Time Source Destination 1 0.000000 127.0.0.1 127.0.0.1 12345 [SYN] Seq=0 Len=0 MSS=16396 TSV=77339 TSER=0 WS=5 Protocol Info TCP 40227 > Frame 1 (74 bytes on wire, 74 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 40227 (40227), Dst Port: 12345 (12345), Seq: 0, Len: 0 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 3c 79 dd 40 00 40 06 c2 dc 7f 00 00 01 7f 00 .<y.@.@......... 24 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras 0020 00 01 9d 23 30 39 d3 14 57 c6 00 00 00 00 a0 02 ...#09..W....... 0030 80 18 69 3b 00 00 02 04 40 0c 04 02 08 0a 00 01 ..i;....@....... 0040 2e 1b 00 00 00 00 01 03 03 05 .......... No. Time Source Destination Protocol Info 2 0.000014 127.0.0.1 127.0.0.1 TCP 12345 > 40227 [SYN, ACK] Seq=0 Ack=1 Win=1048576 Len=0 MSS=16396 TSV=77339 TSER=77339 WS=5 Frame 2 (74 bytes on wire, 74 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 12345 (12345), Dst Port: 40227 (40227), Seq: 0, Ack: 1, Len: 0 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 3c 00 00 40 00 40 06 3c ba 7f 00 00 01 7f 00 .<..@.@.<....... 0020 00 01 30 39 9d 23 d2 d5 80 c2 d3 14 57 c7 a0 12 ..09.#......W... 0030 80 00 e7 8d 00 00 02 04 40 0c 04 02 08 0a 00 01 ........@....... 0040 2e 1b 00 01 2e 1b 01 03 03 05 .......... No. Time Source Destination 3 0.000026 127.0.0.1 127.0.0.1 12345 [ACK] Seq=1 Ack=1 Win=32800 Len=0 TSV=77339 TSER=77339 Protocol Info TCP 40227 > Frame 3 (66 bytes on wire, 66 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) 25 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras Transmission Control Protocol, Src Port: 40227 (40227), Dst Port: 12345 (12345), Seq: 1, Ack: 1, Len: 0 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 34 79 de 40 00 40 06 c2 e3 7f 00 00 01 7f 00 .4y.@.@......... 0020 00 01 9d 23 30 39 d3 14 57 c7 d2 d5 80 c3 80 10 ...#09..W....... 0030 04 01 cc af 00 00 01 01 08 0a 00 01 2e 1b 00 01 ................ 0040 2e 1b .. No. Time Source Destination Protocol Info 4 0.000715 127.0.0.1 127.0.0.1 TCP 40227 > 12345 [PSH, ACK] Seq=1 Ack=1 Win=32800 [TCP CHECKSUM INCORRECT] Len=4 TSV=77339 TSER=77339 Frame 4 (70 bytes on wire, 70 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 40227 (40227), Dst Port: 12345 (12345), Seq: 1, Ack: 1, Len: 4 Data (4 bytes) 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 38 79 df 40 00 40 06 c2 de 7f 00 00 01 7f 00 .8y.@.@......... 0020 00 01 9d 23 30 39 d3 14 57 c7 d2 d5 80 c3 80 18 ...#09..W....... 0030 04 01 fe 2c 00 00 01 01 08 0a 00 01 2e 1b 00 01 ...,............ 0040 2e 1b 7b 00 00 00 ..{... No. Time Source Destination Protocol Info 26 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras 5 0.000808 127.0.0.1 127.0.0.1 40227 [ACK] Seq=1 Ack=5 Win=32768 Len=0 TSV=77339 TSER=77339 TCP 12345 > Frame 5 (66 bytes on wire, 66 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 12345 (12345), Dst Port: 40227 (40227), Seq: 1, Ack: 5, Len: 0 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 34 ae d8 40 00 40 06 8d e9 7f 00 00 01 7f 00 .4..@.@......... 0020 00 01 30 39 9d 23 d2 d5 80 c3 d3 14 57 cb 80 10 ..09.#......W... 0030 04 00 cc ac 00 00 01 01 08 0a 00 01 2e 1b 00 01 ................ 0040 2e 1b .. No. Time Source Destination Protocol Info 6 0.001274 127.0.0.1 127.0.0.1 TCP 12345 > 40227 [PSH, ACK] Seq=1 Ack=5 Win=32768 [TCP CHECKSUM INCORRECT] Len=1 TSV=77340 TSER=77339 Frame 6 (67 bytes on wire, 67 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 12345 (12345), Dst Port: 40227 (40227), Seq: 1, Ack: 5, Len: 1 Data (1 byte) 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 35 ae d9 40 00 40 06 8d e7 7f 00 00 01 7f 00 .5..@.@......... 0020 00 01 30 39 9d 23 d2 d5 80 c3 d3 14 57 cb 80 18 ..09.#......W... 27 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras 0030 04 00 fe 29 00 00 01 01 08 0a 00 01 2e 1c 00 01 ...)............ 0040 2e 1b 69 ..i No. Time Source Destination Protocol Info 7 0.001286 127.0.0.1 127.0.0.1 12345 [ACK] Seq=5 Ack=2 Win=32800 Len=0 TSV=77340 TSER=77340 TCP 40227 > Frame 7 (66 bytes on wire, 66 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 40227 (40227), Dst Port: 12345 (12345), Seq: 5, Ack: 2, Len: 0 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 34 79 e0 40 00 40 06 c2 e1 7f 00 00 01 7f 00 .4y.@.@......... 0020 00 01 9d 23 30 39 d3 14 57 cb d2 d5 80 c4 80 10 ...#09..W....... 0030 04 01 cc a8 00 00 01 01 08 0a 00 01 2e 1c 00 01 ................ 0040 2e 1c .. No. Time Source Destination Protocol Info 8 0.001772 127.0.0.1 127.0.0.1 TCP 12345 [FIN, ACK] Seq=5 Ack=2 Win=32800 Len=0 TSV=77340 TSER=77340 40227 > Frame 8 (66 bytes on wire, 66 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 40227 (40227), Dst Port: 12345 (12345), Seq: 5, Ack: 2, Len: 0 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 28 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras 0010 00 34 79 e1 40 00 40 06 c2 e0 7f 00 00 01 7f 00 .4y.@.@......... 0020 00 01 9d 23 30 39 d3 14 57 cb d2 d5 80 c4 80 11 ...#09..W....... 0030 04 01 cc a7 00 00 01 01 08 0a 00 01 2e 1c 00 01 ................ 0040 2e 1c .. No. Time Source Destination Protocol Info 9 0.041379 127.0.0.1 127.0.0.1 40227 [ACK] Seq=2 Ack=6 Win=32768 Len=0 TSV=77350 TSER=77340 TCP 12345 > Frame 9 (66 bytes on wire, 66 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 12345 (12345), Dst Port: 40227 (40227), Seq: 2, Ack: 6, Len: 0 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 34 ae da 40 00 40 06 8d e7 7f 00 00 01 7f 00 .4..@.@......... 0020 00 01 30 39 9d 23 d2 d5 80 c4 d3 14 57 cc 80 10 ..09.#......W... 0030 04 00 cc 9e 00 00 01 01 08 0a 00 01 2e 26 00 01 .............&.. 0040 2e 1c .. No. Time Source Destination Protocol Info 10 7.872108 127.0.0.1 127.0.0.1 TCP 40227 [FIN, ACK] Seq=2 Ack=6 Win=32768 Len=0 TSV=79307 TSER=77340 12345 > Frame 10 (66 bytes on wire, 66 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 12345 (12345), Dst Port: 40227 (40227), Seq: 2, Ack: 6, Len: 0 29 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 34 ae db 40 00 40 06 8d e6 7f 00 00 01 7f 00 .4..@.@......... 0020 00 01 30 39 9d 23 d2 d5 80 c4 d3 14 57 cc 80 11 ..09.#......W... 0030 04 00 c4 f8 00 00 01 01 08 0a 00 01 35 cb 00 01 ............5... 0040 2e 1c .. No. Time Source Destination Protocol Info 11 7.872211 127.0.0.1 127.0.0.1 12345 [ACK] Seq=6 Ack=3 Win=32800 Len=0 TSV=79307 TSER=79307 TCP 40227 > Frame 11 (66 bytes on wire, 66 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 40227 (40227), Dst Port: 12345 (12345), Seq: 6, Ack: 3, Len: 0 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 34 00 00 40 00 40 06 3c c2 7f 00 00 01 7f 00 .4..@.@.<....... 0020 00 01 9d 23 30 39 d3 14 57 cc d2 d5 80 c5 80 10 ...#09..W....... 0030 04 01 bd 48 00 00 01 01 08 0a 00 01 35 cb 00 01 ...H........5... 0040 35 cb 5. No. Time Source Destination Protocol Info 12 7.872660 127.0.0.1 127.0.0.1 TCP 49814 [FIN, ACK] Seq=0 Ack=0 Win=1024 Len=0 TSV=79307 TSER=1955 12345 > Frame 12 (66 bytes on wire, 66 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 12345 (12345), Dst Port: 49814 (49814), Seq: 0, Ack: 0, Len: 0 30 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 34 09 1d 40 00 40 06 33 a5 7f 00 00 01 7f 00 .4..@[email protected]....... 0020 00 01 30 39 c2 96 9d 11 0e bc 9c 2e 01 bf 80 11 ..09............ 0030 04 00 fa bf 00 00 01 01 08 0a 00 01 35 cb 00 00 ............5... 0040 07 a3 .. No. Time Source 13 7.872775 127.0.0.1 12345 [RST] Seq=0 Len=0 Destination Protocol Info 127.0.0.1 TCP 49814 > Frame 13 (54 bytes on wire, 54 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 49814 (49814), Dst Port: 12345 (12345), Seq: 0, Len: 0 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 28 00 00 40 00 40 06 3c ce 7f 00 00 01 7f 00 .(..@.@.<....... 0020 00 01 c2 96 30 39 9c 2e 01 bf 00 00 00 00 50 04 ....09........P. 0030 00 00 21 21 00 00 ..!!.. No. Time Source Destination Protocol Info 14 7.872963 127.0.0.1 127.0.0.1 TCP 49815 [FIN, ACK] Seq=0 Ack=0 Win=1024 Len=0 TSV=79308 TSER=7743 12345 > Frame 14 (66 bytes on wire, 66 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 12345 (12345), Dst Port: 49815 (49815), Seq: 0, Ack: 0, Len: 0 31 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 34 39 5b 40 00 40 06 03 67 7f 00 00 01 7f 00 .49[@[email protected]...... 0020 00 01 30 39 c2 97 00 d6 27 68 01 4b ab 02 80 11 ..09....'h.K.... 0030 04 00 59 51 00 00 01 01 08 0a 00 01 35 cc 00 00 ..YQ........5... 0040 1e 3f .? No. Time Source 15 7.872996 127.0.0.1 12345 [RST] Seq=0 Len=0 Destination Protocol Info 127.0.0.1 TCP 49815 > Frame 15 (54 bytes on wire, 54 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 49815 (49815), Dst Port: 12345 (12345), Seq: 0, Len: 0 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 28 00 00 40 00 40 06 3c ce 7f 00 00 01 7f 00 .(..@.@.<....... 0020 00 01 c2 97 30 39 01 4b ab 02 00 00 00 00 50 04 ....09.K......P. 0030 00 00 12 c0 00 00 ...... No. Time Source Destination Protocol Info 16 7.873014 127.0.0.1 127.0.0.1 TCP 49818 [FIN, ACK] Seq=0 Ack=0 Win=1024 Len=0 TSV=79308 TSER=54551 12345 > Frame 16 (66 bytes on wire, 66 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 12345 (12345), Dst Port: 49818 (49818), Seq: 0, Ack: 0, Len: 0 32 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 34 0c 48 40 00 40 06 30 7a 7f 00 00 01 7f 00 .4.H@[email protected]...... 0020 00 01 30 39 c2 9a 99 1f d9 53 98 a2 3f 16 80 11 ..09.....S..?... 0030 04 00 2c d5 00 00 01 01 08 0a 00 01 35 cc 00 00 ..,.........5... 0040 d5 17 .. No. Time Source 17 7.873021 127.0.0.1 12345 [RST] Seq=0 Len=0 Destination Protocol Info 127.0.0.1 TCP 49818 > Frame 17 (54 bytes on wire, 54 bytes captured) Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) Internet Protocol, Src: 127.0.0.1 (127.0.0.1), Dst: 127.0.0.1 (127.0.0.1) Transmission Control Protocol, Src Port: 49818 (49818), Dst Port: 12345 (12345), Seq: 0, Len: 0 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E. 0010 00 28 00 00 40 00 40 06 3c ce 7f 00 00 01 7f 00 .(..@.@.<....... 0020 00 01 c2 9a 30 39 98 a2 3f 16 00 00 00 00 50 04 ....09..?.....P. 0030 00 00 e7 51 00 00 ...Q.. 33 | P á g i n a TP4 – Sockets TCP/UDP 66.48 - Seminario de Redes de Computadoras Conclusión: Los sockets ayudan a los procesos de aplicación a comunicarse entre sí utilizando descriptors de archive estándar en Unux. Los dos tipos de sockets de Internet utilizados son: SOCK_STREAM (TCP) y SOCK_DGRAM (UDP). Existen numerosas rutinas para facilitar el proceso de comunicación. Referencias: Libros: • • Unix Network Programming, volumes 1-2 by W. Richard Stevens. TCP/IP Illustrated, volumes 1-3 by W. Richard Stevens and Gary R. Wright Recursos Web: • • Beej's Guide to Network Programming www.ecst.csuchico.edu/beej/guide/net http://www.arrakis.es/~dmrq/beej/clientserver.html 34 | P á g i n a