La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

1 Sockets de Unix Sistemas Informáticos Distribuidos.

Presentaciones similares


Presentación del tema: "1 Sockets de Unix Sistemas Informáticos Distribuidos."— Transcripción de la presentación:

1 1 Sockets de Unix Sistemas Informáticos Distribuidos

2 2 Sockets Parte 1: Manejo de sockets desde C Parte 2: Manejo de sockets desde JAVA

3 3 Sockets en C Parte 1

4 4 APLICACIÓN PRESENTACIÓN SESIÓN TRANSPORTE RED ENLACE FÍSICA APLICACIÓN PRESENTACIÓN SESIÓN TRANSPORTE RED ENLACE FÍSICA MÁQUINA A MÁQUINA B Modelo OSI de ISO

5 5 Familias Familia AF_UNIX: Usa protocolos internos de Unix. Familia AF_INET: Usa protocolos de Internet, como el TCP (Transmisión Control Protocol). Familia AF_CCITT: Norma X.25 de CCITT. Familia AF_NS: Protocolos NS de XEROX. Familia AF_SNA: Protocolos IBM SNA. Familia AF_DECnet. Familia AF_APPLETALK.

6 6 Tipos de conexión Circuito virtual: Mediante la b ú squeda de enlaces libres, se establece un circuito virtual. Conexi ó n permanente hasta el final de la comunicaci ó n. SOCK_STREAM Datagramas: no trabajan con circuitos permanentes. La transmisi ó n se realiza a nivel de paquetes. SOCK_DGRAM

7 7 Direcciones de red struct sockaddr { u_short sa_family; /* familia de sockets: AF_xxxx */ char sa_data[14];/* 14 bytes con la dirección.*/ /* Su codificación depende de la familia */ }; struct sockaddr_un{ short sun_family;/* AF_UNIX */ char sun_path[108];/* Path name */ };

8 8 Direcciones de red (II) struct in_addr{ u_long s_addr;/* 32 bits con la identificación de la red y el host (en binario) */ }; struct sockaddr_in { short sin_family;/*en este caso, AF_INET */ u_short sin_port;/* 16 bits con el número de puerto */ in_addr sin_addr;/* id. red y host */ char sin_zero[8];/* 8 bytes sin usar */ };

9 9 Direcciones de red (III) Número de puerto: se usa para asociar el socket al proceso que se está ejecutando. Si en una misma máquina hay distintos sockets abiertos cada uno de ellos deberá llevar un número de puerto distinto, puesto que todos llevarán la misma dirección de red. Número de puerto: puede tomar valores entre 1024 y El sistema proporciona automáticamente números de puerto que estén libres entre 1024 y 5000 mediante ciertas funciones. Del número 1 al 1024 están reservados al sistema y no pueden ser usados por aplicaciones de usuario. La función int rresvport (int * port) reserva un puerto entre 1024 y Si el número de puerto contiene un 0 antes de efectuar la operación BIND, el sistema también le gestionará un número de forma automática.

10 10 Funciones para convertir direcciones unsigned long inet_addr (const char * cp) Convierte al formato decimal estándar del usuario apuntado por cp al formato binario definido en la estructura struct in_addr. struct in_addr direccion; direccion.s_addr = inet_addr( ) Las direcciones en internet se dan al usuario en formato decimal formado por números del 0 al 255 separados por puntos, que identifican la red o subred y el número de host. char * inet_ntoa ( struct in_addr in ) Hace la operación contraria.

11 11 Funciones para convertir formatos numéricos a) big-endiandirección N: byte más significativo dirección N+1: byte menos significativo (IBM RS6000, SUN,..., TCP,UDP) b) little-endiandirección N: byte menos significativo dirección N+1: byte más significativo DEC Alpha, Intel x86,...)

12 12 Funciones para convertir formatos numéricos (II) unsigned long htonl ( unsigned long hostlong ) Convierte un long del formato de la máquina al de la red. unsigned short htons ( unsigned short hostshort ) Convierte un short del formato de la máquina al de la red. unsigned long ntohl ( unsigned long netlong ) Convierte un long del formato de la red al de la máquina. unsigned short ntohs ( unsigned short netshort ) Convierte un short del formato de la red al de la máquina. struct sockaddr_in servidor_addr; servidor_addr.sin_port = htons(7000);

13 13 Apertura de un punto terminal en un canal. int socket (int af, int type, int protocol); Socket crea un punto terminal para conectarse a un canal bidireccional, devuelve un descriptor del canal. af - Es la familia: AF_UNIX, AF_INET, AF_CCITT, AF_NS,... type - El tipo de conexión: SOCK_STREAM, SOCK_DGRAM protocol - Protocolo particular que se desea usar. Normalmente cada tipo de socket sólo tiene un protocolo, pero si hay más de uno se puede especificar. Si no, se pone un 0. Si todo funciona bien, socket devuelve un descriptor de fichero. En caso contrario devuelve -1, quedando codificado el error en la variable global errno.

14 14 Nombre de un socket int bind(int sfd, const void *addr,int addrlen) Bind une un socket a una dirección de red determinada. Bind hace que el socket con descriptor sfd se una a la dirección de socket que especifica la estructura apuntada por addr y de longitud addrlen. La estructura a la que apunta addr deberá ser struct sockaddr_un en el caso de la familia AF_UNIX, y será struct sockaddr_in en el caso de la familia AF_INET. Si la llamada funciona correctamente, bind devuelve 0, en caso contrario -1.

15 15 Disponibilidad para recibir peticiones de servicio. int listen (int sfd, int backlog) Listen habilita una cola asociada al socket descrito por sfd para alojar las peticiones de conexión que le realicen otros programas. La longitud de esa cola se especifica en backlog. Listen sólo tiene sentido en sockets del tipo SOCK_STREAM. Si listen funciona correctamente devuelve 0, y en caso de error -1.

16 16 Petición de conexión int connect (int sfd,const void *addr,int addrlen) Llamada del proceso cliente para empezar a comunicar. sfd : descriptor del socket. addr: puntero a estructura de dirección del socket remoto con el que se quiere conectar. (struct sockaddr_in). addrlen : tamaño de la estructura. En SOCK_DGRAM, connect especifica la dirección del socket remoto, pero no se conecta con él. En SOCK_STREAM, connect intenta conexión devolviendo error si no se consigue (cuando está activo el modo de acceso no bloqueante O_NDELAY). El modo de acceso al socket se puede modificar usando la función fcntl(). fcntl ( sfd, F_SETFL, O_NDELAY ) La conexión correcta devuelve un 0. Se devuelve -1 en caso de error.

17 17 Aceptación de conexión int accept(int sfd, void *addr, int *addrlen) Acepta demanda de servicio en sockets orientados a conexión. sfd : descriptor del socket. accept extrae la primera llamada de la cola que ha creado listen sobre el socket, y después crea un nuevo socket con las mismas propiedades que sfd, reservándole un nuevo descriptor de fichero. Si no hay peticiones para extraer de la cola, accept permanecerá bloqueada a menos que esté activo el control de acceso no bloqueante (O_NDELAY) en cuyo caso devolverá un error. addr debe apuntar a una estructura local de dirección de socket. La propia llamada accept rellenará esa estructura con la dirección del socket remoto que ha pedido la conexión. addrlen debe ser un puntero para permitir que la llamada sobrescriba sobre él el tamaño real de la dirección leída. Si no error, devolverá descriptor del nuevo socket. En error devuelve -1.

18 18 Lectura o recepción de mensajes de un socket int read (int sfd, char* buf, unsigned nbyte) Read lee nbyte bytes del socket sfd y los almacena en el buffer apuntado por buf. Si no hay error, devuelve el número de bytes leídos. ssize_t readv (int sfd, const struct iovec* iov, size_t iovcnt) struct iovec{ caddr_t iov_base;/* Dirección inicial del buffer */ int iov_len; /* Tamaño en bytes del buffer */ }; Readv lee los datos del socket sfd y los distribuye entre los distintos buffers especificados por el array iov. El total de elementos de iov viene especificado por iovcnt: iov[0],.., iov[iovcnt-1]

19 19 Lectura o recepción de mensajes de un socket (II) int recv (int sfd, void *buf, int len, int flags) int recvfrom (int sfd,void *buf,int len,int flags,void *from, int fromlen) int recvmsg (int sfd, struct msghdr msg[], int flags) sfd : descriptor del socket del que se lee. buf : puntero al buffer donde se escriben los datos leídos. len : número máximo de bytes que cabe en el buffer. flags: es una combinación de 2 bits: MSG_PEEK=1 el dato leído del socket no se vacía, se volverá a leer. MSG_OOB=1 lee sólo los datos "urgentes" (mensajes fuera de banda). Por lo tanto, flags puede valer 0 (00), 1 (01), 2 (10) o 3 (11). En AF_UNIX no puede tener activos ninguno de los dos anteriores. Las 3 funciones devuelven el total de bytes leídos del socket.

20 20 Lectura o recepción de mensajes de un socket (III) int recv (int sfd, void *buf, int len, int flags) int recvfrom (int sfd,void *buf,int len,int flags,void *from, int fromlen) int recvmsg (int sfd, struct msghdr msg[], int flags) En SOCK_STREAM, las llamadas sólo pueden usarse después de haber establecido una conexión con CONNECT. En los SOCK_DGRAM no es necesario, si se hace, entonces se recibe siempre del mismo, si no, se recibe de cualquiera. Recvfrom puede devolver la dirección del socket desde el que se enviaron los datos. Si from<>NULL, al volver, la dirección del socket origen se recibirá en la estructura apuntada, y fromlen debe contener el tamaño de la dirección apuntada por from (al llamar a la función, la que tenga from, y al salir la que ha leído realmente) En SOCK_STREAM, recvfrom = recv.

21 21 Lectura o recepción de mensajes de un socket (IV) int recv (int sfd, void *buf, int len, int flags) int recvfrom (int sfd,void *buf,int len,int flags,void *from, int fromlen) int recvmsg (int sfd, struct msghdr msg[], int flags) recvmsg permite que los datos leídos puedan distribuirse entre varios buffers. Así msg es un array de cabeceras de mensaje con la siguiente estructura: struct msghdr { caddr_t msg_name;/* dirección de socket (opcional) */ int msg_namelen;/* tamaño de la dirección de socket */ struct iovec* msg_iov; /* array de buffers sobre los que distribuir los datos leídos */ int msg_iovlen;/* num. de elementos del array msg_iov */ caddr_t msg_accrights;/* derechos de acceso */ int msg_accrightslen;/* tamaño de msg_accrights */};

22 22 Escritura o envío de mensajes a un socket int write (int sfd, char* buf, unsigned nbyte) Write escribe nbyte bytes del buffer apuntado por buf en el socket sfd. Si no hay error, devuelve el número de bytes escritos realmente. ssize_t writev (int sfd, const struct iovec* iov, size_t iovcnt) Writev escribe los datos en el socket sfd tomándolos de los distintos buffers especificados por el array iov. El total de elementos de iov viene especificado por iovcnt. Writev devuelve el número total de bytes escritos.

23 23 Escritura o envío de mensajes a un socket (II) int send (int sfd, void *buf, int len, int flags) int sendto (int sfd, void *buf, int len, int flags, void * to, int tolen) int sendmsg (int sfd, struct msghdr msg[], int flags) sfd : descriptor del socket donde se escribe. buf : puntero al buffer de donde se leen los datos a escribir. len : número de bytes en el buffer. flags: puede valer 0 o MSG_OOB. (MSG_PEEK no tiene sentido aquí) Las 3 funciones devuelven el total de bytes escritos en el socket. En SOCK_STREAM, las llamadas sólo pueden usarse después de haber establecido una conexión con CONNECT. En los SOCK_DGRAM no es necesario.

24 24 Obtención de nombres de socket int getsockname(int sfd, void* addr, int addrlen) int getpeername(int sfd, void* addr, int addrlen) En la familia SOCK_STREAM. Getsockname devuelve sobre la estructura apuntada por addr, la dirección del socket de descriptor sfd. Getpeername devuelve sobre la estructura apuntada por addr, la dirección del socket que se encuentra conectado al socket de descriptor sfd. addrlen indica el tamaño en bytes de la estructura apuntada por addr.

25 25 Nombre del nodo actual int gethostname (char* hostname, size_t size) Se usa para determinar el nombre oficial que tiene un nodo en la red. gethostname devuelve en el array apuntado por hostname el nombre oficial de host del ordenador que hace la llamada. Size contiene la longitud de ese array.

26 26 Pipes con sockets int socketpair(int family, int type, int protocol, int sockvec[2]) Crea un par de sockets que permiten la comunicación bidireccional. family, type y protocol tiene el mismo significado que en la definición de socket aunque, por ahora, sólo admite la familia AF_UNIX. sockvec es un vector que contendrá los 2 descriptores de los sockets generados.

27 27 Cierre del socket int close (int sfd) cierra el socket en los dos sentidos de recepción y envío. int shutdown(int sfd, int how) Si how=0 cierra recepción de datos, 1 cierra envío de datos y 2 cierra ambos.

28 28 Lectura del fichero etc/hosts struct hostent* gethostent(); struct hostent* gethostbyname(char* name) struct hostent* gethostbyaddr(const char* addr, int len, int type) int sethostent(int stayopen) int endhostname() etc/hosts contiene la información sobre todas las direcciones internet y los nombres de host de todos los nodos conectados a la red. Si nuestra red tiene un servidor de nombres (DNS), es éste el que resuelve la correspondencia entre direcciones IP y nombres de máquinas.

29 29 Lectura del fichero etc/hosts (II) struct hostent{ char* h_name; char** h_aliases; int h_addrtype; int h_lenght; char** h_addr_list }; #define h_addr h_addrlist[0] /* Para compatibilizar */ h_name: nombre oficial del host. h_aliases: array con nombres alternativos del host h_addrtype: Siempre AF_INET. h_lenght: longitud en bytes de la estructura. h_addr_list: array de direcciones de red a las que responde el host. La lista se devuelve en formato de trabajo interno de la máquina (unsigned long), no como cadena de caracteres.

30 30 Lectura del fichero etc/hosts (III) struct hostent* gethostent(); struct hostent* gethostbyname(char* name) struct hostent* gethostbyaddr(const char* addr, int len, int type) int sethostent(int stayopen) int endhostname() Gethostent: lee la siguiente línea del fichero devolviendo la estructura anterior. Si es la primera, además abre el fichero para lectura. Si es la última, devuelve NULL. Sethostent abre el fichero para lectura y lo deja preparado para leer en la primera línea. Si además stayopen es distinto de 0, después de cada llamada de gethostent no se cierra el fichero. Endhostent cierra el fichero. Gethostbyname lee secuencialmente el fichero hasta encontrar el nombre de host, o su alias, que coincide con name. Gethostbyaddr hace lo propio con la dirección addr con longitud len.

31 31 Esquema general C/S Proceso ServidorProceso Cliente proceso hijo proceso padre Abrir canal Publicar dirección Esperar petición servicio fork Atender cliente Fin hijo Abrir canal Contactar servidor Pedir servicio Esperar respuesta Fin cliente

32 32 Esquema Cliente-Servidor con sockets orientados a conexión socket( ) bind( ) listen( ) accept( ) read( ) write( ) socket( ) connect( ) write( ) read( ) close( ) Proceso ServidorProceso Cliente

33 33 Esquema Cliente-Servidor con sockets orientados a datagrama socket( ) bind( ) recvfrom() sendto( ) socket( ) bind( ) sendto( ) recvfrom() close( ) Proceso ServidorProceso Cliente

34 34 Bibliografía Márquez García, Francisco Manuel. UNIX, programación avanzada. RA-MA, 1993 Rifflet, J.M. Comunicaciones en UNIX McGraw-Hill, 1992

35 35 Sockets en JAVA Parte 2

36 36 Sockets en JAVA Modelo general SERVIDOR:CLIENTE: ServerSocket(port#,timeout)Socket(host,port#) accept() OutputStreamInputStream close()

37 37 Conexión cliente Socket miCliente; miCliente = new Socket(maquina, numeroPuerto); Socket miCliente; try{ miCliente = new Socket(maquina,numeroPuerto); } catch ( IOException e ) { System.out.println ( e ); }

38 38 Conexión servidor Socket miServicio; try{ miServicio = new ServerSocket(numeroPuerto); } catch ( IOException e ) { System.out.println ( e ); } Socket socketServicio = null; try{ socketServicio = miServicio.accept(); } catch ( IOException e ) { System.out.println ( e ); }

39 39 Creación Streams entrada DataInputStream entrada;(--- CLIENTE ---) try { entrada = new DataInputStream( miCliente.getInputStream() ); } catch ( IOException e ) { System.out.println ( e ); } DataInputStream entrada;(--- SERVIDOR ---) try { entrada = new DataInputStream( socketServicio.getInputStream() ); } catch ( IOException e ) { System.out.println ( e ); }

40 40 DataInputStream Lectura del socket: read() readChar() readInt() readDouble() readLine()

41 41 Creación Streams salida PrintStream salida;(--- CLIENTE y SERVIDOR ---) try { salida = new PrintStream( miCliente.getOutputStream() ); } catch ( IOException e ) { System.out.println ( e ); } DataOutputStream salida;(--- CLIENTE y SERVIDOR ---) try { entrada = new DataOutputStream(miCliente.getOutputStream() ); } catch ( IOException e ) { System.out.println ( e ); }

42 42 PrintStream// DataOutputStream PrintStream: write() println() DataOutputStream: writeBytes()

43 43 Cierre Sockets CLIENTE: PrintStream salida; try { salida.close(); entrada.close(); miCliente.close(); } catch ( IOException e ) { System.out.println ( e ); } SERVIDOR: PrintStream salida; try { salida.close(); entrada.close(); socketServicio.close(); miServicio.close(); } catch ( IOException e ) { System.out.println ( e ); }

44 44 Clases útiles Socket : objeto básico ServerSocket : socket de servidor DatagramSocket : socket datagrama DatagramPacket : paquete datagrama MulticastSocket : comunicación en grupo SocketImpl : interfaz para crear un modelo de comunicación


Descargar ppt "1 Sockets de Unix Sistemas Informáticos Distribuidos."

Presentaciones similares


Anuncios Google