Unidad III Primitivas de Sincronización M.C. Juan Carlos Olivares Rojas Temario • 3.1. Introducción 3.2. Comunicación • sockets, RPC, share memory • 3.3. 3 3 Sincronización • Semáforos, colas, memoria compartida y monitores Temario Propuesto p • 3.1. Introducción • 3.2. Sincronización: Semáforos, colas, memoria compartida y monitores • 3.3. 3 3 Comunicación: sockets, sockets RPC RPC, share memory 3.1. Introducción • Para lograr la distribución de procesos se requiere de mecanismos que permitan coordinar y controlar la ejecución de procesos en ambientes no centralizados, ya sean de manera local y remota. • Los primeros protocolos para la distribución de procesos remotos fueron para máquinas homogéneas. Introducción • La mayoría del control de procesos se hace a nivel de sistema operativo a través de las llamadas del sistema. • El sistema de archivo forma parte importante de las primitivas de sincronización entre procesos. Introducción • Una forma básica de sincronización entre procesos es redireccionar el flujo de entrada, teniendo la entrada estándar <, la salida estándar > y la tubería | para redireccionar la salida de un programa sea la entrada de otra. • ls > archivo.txt; mysql < respaldo.sql • cat archivo archivo.txt txt | grep c c* Introducción • Otra forma de comunicación fue la estandarización de sistemas heterogéneos con interfaz común UUCP (Unix to Unix Copy Protocol) que dio origen a los comandos R (rcopy, rlogin, rsh). • rlogin [email protected] • rsh [email protected] 3.2. Sincronización • • • • • 3.2.1 IPC 3.2.2 Semáforos 3.2.3 Colas (mensaje) 3.2.4 Memoria compartida 3 2 5 Monitores 3.2.5 Comunicación • La comunicación entre procesos (IPC) es parte fundamental de las primitivas de sincronización de un sistema distribuido. • Los mecanismos de comunicación entre procesos no sólo aplican a aplicaciones distribuidas sino a cualquier tipo. Procesos • Son la unidad básica de atención del sistema operati o operativo. • Se pueden copiar procesos en diferentes segmentos del sistema operativo. • Los procesos son dependientes del sistema operativo por lo que no se ejecutan en todos los sistemas. Procesos Unix • Los procesos se crean con fork() #include <sys/types.h> pid t pid; pid_t pid = fork() • Se pueden copiar procesos con la familia de funciones exec. fork() () if (pid == -1) perror(“Error al crear proceso”); else { if (pid == 0) /*Proceso hijo*/ else /*Proceso padre*/ } Terminación de procesos p • Cuando un proceso termina devuelve un valor de retorno t all proceso padre. d • T Todos d los l procesos tienen ti un proceso padre. d E t Este código de retorno puede ser consultado a través de la variable de entorno $? • La forma más fácil de salir es devolver un código de retorno (e.g., return 0). Terminación de procesos p • Otra forma de salir es a través de exit(), realiza aparentemente el mismo comportamiento, ayuda a desbloquear procesos en espera. • La función atexit() permite definir una función que se ejecutará al finalizar un programa. Terminación de procesos p • A el código de estado de un proceso formalmente se llama señal. señal • Un proceso huérfano es aquel que se ha quedado sin padre. • Un proceso zombi es aquel que se ha quedado ocupando una posición de la tabla de descriptor de procesos. wait() () • En algunas ocasiones un proceso padre necesita esperar a que q e sus s s hijos termine. termine Para ello necesita sincronizarse los procesos. procesos • La función que nos permite parar un proceso hasta que termine otro es wait • pid = wait(&estado); wait() () • Algunas macros que nos ayudan en este proceso son: • • • • • WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG WCOREDUMP Más sobre procesos p • Un ejemplo de clonación de procesos es la ejecución de la función system() que nos permite ejecutar una llamada al sistema, generalmente un comando de la shell. • hijo = getpid(); • Padre = getppid(); • Grupo = getpgrp(); Identificadores de usuario y de grupo • En muchas ocasiones no sólo es necesario conocer los identificadores de procesos sino conocer los usuarios y los grupos. grupos • • • • uid_t getuid(); /*usuario real*/ uid_t geteuid(); /*usuario extendido*/ gid_t getgid(); gid_t g g getegid(); g (); Variables de entorno • En algunos casos es necesario compartir algunos valores entre aplicaciones, esto se puede hacer a través de la variable de entorno. • Las variables de entorno pueden verse con el comando env (ambiente). Muchos comandos muestran información a través de este entorno. Variables de entorno • Hay algunas variables disponibles en la mayoría de los sistemas como HOME, SHELL, TERM, PATH. • Pueden accederse de manera individual haciendo eco en la pantalla con echo. • char *valor = getenv(“TERM”); Variables de entorno • char *var1 = “VARIABLE=valor” • putenv(var1); /*Coloca una variable en el entorno*/ • La función sleep() permite dormir un proceso una cantidad determinada de milisegundos. Señales • Definidas en <signal.h> • • • • • • • • • 1 SIGHUP 2 SIGINT 3 SIGQUIT 4 SIGILL 5 SIGTRAP 6 SIGIOT 7 SIGEMT 8 SIGFPE 9 SIGKILL • • • • • • • • • • 10 SIGBUS 11 SIGSEGV 12 SIGSYS 13 SIGPIPE 14 SIGALARM 15 SIGTERM 16 SIGUSR1 17 SIGUSR2 18 SIGCLD 19 SIGPWR Señales • int kill(pid, sig) sirve para mandar una señal de un proceso a otro. • pid > 0 proceso; pid = 0 a todos los procesos que pertenecen al mismo grupo. • La función signal sirve para capturar una señal y realizar una función con ella. Señales main() { void id sigint_handler(); i i t h dl () if(signal(SIGINT,sigint_handler)== SIG_ERR) perror(“Error perror( Error en la señal señal”); ); …….. } void sigint_handler(int sigint handler(int sig) { printf(“señal recibida”); } 3.2.1 IPC • El mecanismo de comunicación entre procesos más famosos es el IPC (Inter Process Comunication) de Unix System V. • El otro punto a tratar es sobre los mecanismos de intercomunicación entre entidades de procesamiento diferentes con diferentes sistemas operativos: POSIX. POSIX Tuberías • Se pueden procesos. utilizar • int pipe(tuberia); • int tuberia[2]; • tuberia[0] • tuberia[1] tuberías desde los Tuberías • Al dejar de utilizar una tubería, esta se debe de cerrar en sus dos extremos: close(pipe). • Por un extremo de la tubería se lee, y por el otro se escribe. Ya depende de la lógica del programa ubicar que lado escribe y que lado lee. En general, primero se escribe y luego se lee. Tuberías • Para escribir en una tubería se realiza lo siguiente: write(tuberia[1] write(tuberia[1], mensaje, mensaje strlen(mensaje)+1). • Para leer: read(tuberia[0], mensaje, MAX) • Las tuberías no son bidireccionales, bidireccionales sólo van en un sentido, pero se pueden utilizar dos tuberías para pasar mensajes en ambas direcciones. Tuberías • Las tuberías utilizadas sólo están disponibles para los descendientes de un proceso que lo crean. Por este motivo, no están disponible para otros procesos. • Las tuberías entre procesos iguales se les llama sin nombre. El otro tipo de tuberías tienen nombre y generalmente se les llama FIFO. Tuberías • Las tuberías con nombre se manejan igual que las tuberías sin nombre con la salvedad de que presentan un nombre que ocupa una entrada de directorio. • Se trabajan igual que un archivo sólo que se bloquea cuando un proceso escribe en la tubería. Tuberías • Para crear una tubería con nombre desde shell se debe ejecutar: mknod fifo_1 fifo 1 p • Desde programación las tuberías con nombre se crean: mknod(“tubo”, S_IFIFO | permisos, 0) • Las comunicaciones vistas hasta ahora son half-duplex half duplex. Se puede utilizar un poll o select para realizar comunicación full-duplex 3.2.2 Semáforos • Los semáforos son mecanismos permiten sincronizar procesos. procesos que • Todos los mecanismos IPC tienen una entrada en una tabla especial con una llave definida por el usuario. • Los posibles valores de la llave son IPC PRIVATE IPC_CREATE, IPC_PRIVATE, IPC CREATE IP IP_EXECL, EXECL entre otros. Semáforos • Cada entrada de la tabla tiene un registro de permisos ((rw), p ), información de estado y llamadas de control. • Las llaves son del tipo key_t. Para crear una llave se utiliza: #include <types.h> y p #include <sys/ipc.h> key_t ftok(path, id) Llaves key_t llave; if((llave= ftok(“/etc/ntp.conf”, ‘A’) == (key_t)-1) /*Error al crear la llave*/ • ipcs se utiliza para ver los mecanismos ipc asignados (-q, -m, -s, -b) • ipcrm se utiliza para liberar recursos (-q msqid, -m shmid, -s semid) Semáforos • Es un mecanismo para prevenir colisiones cuando uno o más procesos solicitan simultáneamente un recurso. • Dijsktra los define como un objeto tipo entero en los cuales se puede aplicar dos operaciones: P (Proberen, comprobar) y V (Verhogen, incrementar), donde P sirve para obtener el recurso y V para liberarlo. Semáforos • Las operaciones sobre un semáforo son semget para crear un semáforo o habilitar uno existente, semctl para realizar operaciones de control e inicialización, semop para realizar operaciones P y V. #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> y int semget(key, nsems, semflg) Semáforos int llave, semid; if((llave= ftok(“auxiliar”, ‘K’)) ==(key_t)-1) /*Tratamiento del error*/ if((semid= semget(llave, semget(llave 4, 4 IPC_CREAT IPC CREAT | 0600)) == -1) /*Error al crear el semáforo*/ Semáforos int semctl(semid, semnum, cmd, arg) union nion semun{ sem n{ int val; struct semid_ds *buf; ushort *array; }arg; • Las opciones de control son: GETVAL, SETVAL GETPID, SETVAL, GETPID GETNCNT, GETNCNT GETZCNT, GETZCNT GETALL, SETALL, IPC_STAT, IPC_SET Semáforos ushort asem; asem[0]=5; asem[1]=3; asem[2]=4; asem[3]=8; semctrl(semid, 0, SETALL, asem) valor = semctrl(semid, 3, GETVAL, 0) int semop(semid, sops, nsops) struct sembuf *sops; Semáforos struct sembuf{ ushort sem_num; sem num; short sem_op; short sem_flg; sem flg; }; • Si semop es negativo se decrementará (P), si se incrementa (V) y si es 0 no hace nada. nada • Las banderas son: IPC_WAIT, IPC WAIT IPC_NOWAIT, IPC NOWAIT SEM_UNDO Semáforos struct sembuf operacines[4]; Operaciones[0].semnum = 1; Operaciones[0].sem op = -1; Operaciones[0].sem_op 1; Operaciones[0].sem_flg = 0; Operaciones[1] semnum = 4; Operaciones[1].semnum Operaciones[1].sem_op = 1; Operaciones[1].sem_flg = 0; semop(semid, operaciones, 2); 3.2.3 Colas (mensaje) ( j ) • La filosofía de las colas de mensajes es similar a las tuberías, pero con mayor versatilidad. • Una cola es una estructura de datos gestionada por el kernel, en la cual varios procesos pueden escribir sobre ella. El sincronismo para evitar colisión lo realiza el kernel. Colas de mensajes j #include <sys/msg.h> int msgget(key, msgget(ke msgflg) If((msqid= msgget(llave, IPC_CREATE | 0600)) == -1) /*Error al crear la cola de mensajes*/ • msgctrl(msq, cmd, buf) sirve para leer y modificar la información estadística y de control de una cola. Colas de mensajes j • Los comandos de control son: IPC_STAT, IPC SET IPC_SET, IPC RMID IPC_RMID. Por ejemplo: msgctrl(msqid, IPC_RMID, 0); • Las operaciones básicas de una cola de mensajes j son enviar i y recibir ibi los l mensajes j que se realizan con las siguientes funciones: int msgsnd(msqid, g ( q msgp, gp msgsz, g msgflg); g g) int msgrcv(msqid, msqp, msgtyp, msgflag); Cola de mensajes j • El parámetro msgtyp indica el tipo de mensaje que se desea leer: 0 para el primer mensaje, > 0 el primer mensaje de tipo msgtyp que haya en la cola, <0 lee el primer mensaje que sea menor o igual al valor absoluto de msgtyp y además sea el mensaje más pequeño de los que hay. Cola de mensajes j struct{ long tipo; char cadena[20]; }mensaje; strcpy(mensaje.cadena, “SD1”); mensaje.tipo = 1; longitud = strlen(mensaje.cadena) ( g ( q , j , g , ) ) /*Err*/ if(msgsnd(msqid,&mensaje,longitud,0)==-1) if(msgrcv(msqid,&mensaje,longitud,1,0) ==-1) /*Er*/ 3.2.4 Memoria compartida p • La forma más rápida de comunicar dos procesos es que compartan t una zona de d memoria i compartida. • Las primitivas para manipular memoria compartida son: shmget para crear una zona d ememoria compartida o utilizar una ya creada, shmctl para acceder y modificar la información administrativa y de control, shmat para unir una zona de memoria compartida a un proceso, y shmdt para separa una zona previamente unida. Memoria compartida p #include <sys/shm.h> int shmget(key, size, shmflg); int shmid; if((shmid = shmget(IPC_PRIVATE, shmget(IPC PRIVATE IPC_CREAT | 0600)) == -1) /*E /*Error all crear memoria i compartida*/ tid */ 4096 4096, Memoria compartida p • int shmctl(shmid, cmd, buf) • cmd indica la operación la cual puede ser: IPC_STAT, IPC_SET, IPC_RMID, SHM LOCK, SHM_UNLOCK. SHM_LOCK, SHM UNLOCK. • struct shmid_s shmid s *buf • smctl(shmid, IPC_RMID, 0); Memoria compartida p char *shmat(shmid, shmaddr, shmflg); i t shmdt(shmaddr); int h dt( h dd ) float *memoria; shmid = shmget(llave, MAX IPC CREAT | 0600); IPC_CREAT 0600) memoria = shmat(shmid, 0, 0); /*Operar memoria*/ shmdt(memoria); shmctl(shmid, IPC_RMID, 0); * sizeof(float), 3.2.5 Monitores • Es un procesos que se encarga de verificar el funcionamiento de algún recurso garantizando la exclusión mutua (mutex). • En un monitor los procesos se bloquean y desbloquean. • Pueden existir diversas implementaciones no estandarizadas de un monitor. monitor Hilos • Son procesos ligeros ya que no se duplican completamente, sólo duplican su segmento de código. Por tal motivo, comparten datos fácilmente, la desventaja es que ocurren muchos problemas del tipo “race conditions”, pero al igual que IPC se soluciona con mecanismos como regiones críticas, zonas de exclusión mutua, etc. Hilos • PThreads (POSIX Threads) es la biblioteca para la creación de hilos más implementada en sistemas *X. • Se utiliza la biblioteca pthread por lo que algunos compiladores ya la incluyen de manera predeterminada sino habrá que indicar su uso: gcc … -lpthread Hilos • Crear hilos: int pthread_create(pthread_t *thread, pthread_attr_t *attr, void * (*start_routine)(void *), void *arg) • Esperar la finalización de hilos: int pthread join(pthread t pthread_join(pthread_t **thread_return) th th, void Hilos • No guardar estado del hilo: int pthread_detach(pthread_t h) • Salir de un hilo: pthread exit(void *retval) pthread_exit(void • Biblioteca a utilizar: #include <pthread.h> Hilos typedef struct parametros { int id; char *nombre }; void *funcion(parametros *p) { printf(“%s %d”, p->cadena, p->id); pthread_exit(&(p->id)) } Hilos • Referencia asi mismo: Yo = pthread_self(); /*Demás funciones*/ • Enviar una señal a un hilo: pthread_kill(pthread p (p _t hilo,, int señal); ); • Los hilos no están tan extendidos por que existen muchas variantes: hilos mach, hilos solaris,, Gthreads,, etc. Hilos • Mutex: pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr_t th d t tt t *attr) * tt ) int pthread_mutex_lock(pthread_mutex_t *mutex) int pthread_mutex_lock(pthread_mutext_t *mutex) int pthread_mutext_destroy(pthread_mutext_t *mutex) 3.3 Comunicación • • • • • • 3.3.1 Sockets 3.3.2 RPC 3.3.3 RMI 3.3.4 CORBA 3 3 5 Servicios Web 3.3.5 3.3.6 Otras tecnologías distribuidas 3.3.1 Sockets • Los sockets son el mecanismo de sincronización distribuida más importante. • Se les denomina conectores por que pueden unir un proceso cliente y un proceso servidor, de manera semejante a como se puede unir un enchufe de un dispositivo eléctrico con su respectivo zócalo. Sockets • El mecanismo de sockets más conocido es el referente a la API de Berkeley. • Está API está implementado en prácticamente todos los sistemas Unix, por lo que se maneja C, pero también está portado a otras arquitecturas como Windows (WinSock) y a otros lenguajes como Java Sockets • Los sockets trabajan sobre capa 4 (Transporte) del modelo OSI, aunque algunos autores la ubican en la capa 5 (Sesión). • Para la comunicación de procesos remotos se necesita conocer la dirección de la máquina destino y el puerto donde se va a escuchar. Sockets • Los sockets no están casados con ningún tipo de red, por lo que se pueden implementar en diversos protocolos de red como IPX/SPX, NetBEUI, TCP/IP, siendo este último el más importante. • Para hacer uso de sockets se necesitan dos cosas: una familia o protocolo a utilizar para la comunicación y un tipo de conexión. Sockets • Se utiliza la biblioteca <sys/socket.> • Se utilizan las siguientes estructuras de datos: struct sockaddr { u_shortsa_family_; h t f il /*F ili */ /*Familia*/ char sa_data[14]; /*Dirección*/ }; Sockets • Para utilizar sockets TCP/IP se debe emplear la familia o protocolo Internet, la cual define sus direcciones en <netinet/in.h> y son: struct in_addr { u long s_addr; u_long s addr; //*32 32 bits bits*// }; Sockets struct sockaddr_in { short sin_familiy; /*AF_INET*/ u_short sin_port; /*16 bits*/ struct in_addr sin_addr; /*32 bits*/ y no usados*/ char sin_zero[8]; /*8 bytes }; • También existen sockets para sistemas Unix de manera nativa llamados “Unix Unix Domain” Sockets • La biblioteca <sys/un.h> define la siguiente estructura: struct t t sockaddr_un k dd { short sun_family; /*AF_UNIX*/ char sun_family; /*Ruta*/ }; • Los sockets se basan en la arquitectura cliente/servidor Funciones de un servidor 1. Abrir el canal de comunicación e informar a la red su dirección y su disposición para aceptar peticiones de servicio. 2. Esperar a que un cliente pida un servicio 3. Atender un cliente (servidor interactivo) a la vez o crear un proceso hijo (servidor concurrente) 4. Volver al punto 2 para esperar nuevas peticiones. peticiones Funciones de un cliente 1. Abrir el canal de comunicaciones conectarse a la dirección del servidor. y 2. Enviar al servidor un mensaje de petición de servicio y esperar hasta recibir la respuesta. 3. Cerrar el canal de comunicaciones y terminar la ejecución. ejecución Primitivas de sockets en el servidor • Las primitivas son para comunicación orientada a conexión (Stream) socket(); bind(); listen(); acept(); read(); write(); Primitivas de sockets en el cliente • Las primitivas de sockets bloqueantes y no bloqueantes socket(); connect(); write(); read(); close(); pueden ser Primitivas de sockets en el servidor • Las primitivas son para comunicación entre procesos no orientada a conexión (Datagramas). socket(); bind(); recvfrom(); sendto(); Primitivas de sockets en el cliente socket(); bind(); sendto(); recvfrom(); shutdown(); Socket(int af, int type, int protocol) • Tipos: SOCK_STREAM, SOCK STREAM, SOCK_DGRAM SOCK DGRAM Sockets bind(int sfd, const void *addr, int addrlen); listen(int sfd, int backlog); connect(int sfd, sfd void *addr, *addr int addrlen); accept(int sfd, void *addr, int *addrlen); Sockets • Para establecer una comunicación a través de sockets se necesitan 5 requerimientos: • • • • • Dirección del servidor Puerto del servidor Dirección del cliente Puerto del cliente Canal de comunicación abierto Sockets • Para leer datos de un socket se pueden utilizar las siguientes primitivas: read, readv, recv, recvfrom y recvmsg; siendo las más utilizadas read y recv(sfd, buf, len, flags). • Para escribir datos en un socket se utilizan las siguientes primitivas: write, writev, send, sendto y sendmsg, siendo las más utilizadas write y send(sfd, buf, len, flags). Sockets • Se necesitan funciones de conversión para poder d homogenizar h i l diferencias las dif i existentes i t t entre las diversas arquitecturas de cómputo. #include <arpa/inet.h> p • inet inet_addr(char addr(char *)) convierte una dirección IP en formato de cadena a su representación en bytes. bytes Sockets • char *inet_ntoa(struct in_addr) convierte una dirección IP a cadena. unsigned long htonl(unsigned long hostlong); unsigned short htons(unsigned short hshort); unsigned long ntohl(unsigned long netlong); unsgined long ntohs(unsigned short netsho); • h:host n:network l:long s:short Servidor stream int sfd, nsfd, pid; struct sockaddr_in ser, cli; int tam_clie; tam clie; if((sd = socket(AF_INET, socket(AF INET SOCK_STREAM, SOCK STREAM 0)) == -1) /*Error al crear el socket*/ /*Dirección del servidor*/ ser.sin_family = AF_INET; Servidor stream ser.sin_addr.s_addr = “148.208.209.25”); ser.sin_port = htons(24400); ( ) if(bind(sfd &ser, if(bind(sfd, &ser sizeof(ser)) == -1) /*Error al publicar dirección*/ listen(sfd, 5); inet_addr( Servidor stream for(;;){ /*Un servidor siempre está activo*/ tam_clie = sizeof(clie); if((nsfd = accept(sfd, &clie, &tam_clie)) == -1) /*Error al aceptar peticiones*/ if((pid = fork()) ==-1) /*Error al crear subproceso*/ else if(pid ==0) /*Hijo atiende peticiones*/ /*Código padre*/ close(sfd); } Cliente stream int sfd; struct sockaddr_in ser; if((sfd = socket(AF_INET, SOCK_STREAM, 0)) ==-1) //*Error Error al crear el socket socket*// /*Dirección del servidor*/ ser.sin_family = AF_INET; Cliente stream ser.sin_addr.s_addr = “148.208.209.25”); ser.sin_port = htons(24400); ( ) inet_addr( if(connect(sfd, &ser, if(connect(sfd &ser sizeof(ser)) ==-1) //*Error Error al conectar*/ send(); read(); …. close(sfd); Servidor datagrama g int sfd; struct sockaddr_in ser, clie; if((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) //*Error Error al crear socket datagrama datagrama*// /*Dirección del servidor*/ ser.sin_family = AF_INET; ser.sin_port = htons(21100); Servidor datagrama g ser.sin_addr.s_addr “142.208.209.25”); = inet_addr( if(bind(sfd, &ser, sizeof(ser)) ==-1) /*Error al ligar el socket socket*// recvfrom(); sendto(); close(sfd); Cliente datagrama g int sfd; struct sockaddr_in ser, clie; if((sfd = socket(AF_INET, SOCK_DGRAM, 0)) ==-1) //*Error Error al crear el socket socket*// /*Dirección del servidor*/ ser.sin_family = AF_INET; ser.sin_port = htons(21100); Cliente datagrama g ser.sin_addr.s_addr “148.208.209.25”); = /*Dirección del cliente*/ cli sin family = AF_INET cli.sin_family AF INET cli.sin_addr.s_addr inet addr(INADDR ANY); inet_addr(INADDR_ANY); cli.sin_port = htons(0); inet_addr( = Cliente datagrama g if(bind(sfd, &cli, & sizeof(cli)) ==-1) /*Error*/ sento(); recvfrom(); … close(sfd); • Existen otras funciones auxiliares de socket: • gethostname(char *nombre, nombre, size_t size t tipo); Otras funciones de sockets • shutdown(int sfd, int how) cierra la comunicación del socket. socket Los socket por naturaleza son bidireccionales. Si how es 0 se deshabilita la recepción de datos, datos si es 1 se deshabilita el envío y si es 2, se cierra todo (similar a close()). close()) • Para utilizar nombres de dominio se utilizan: struct hosent *gethostent(); Otras funciones de sockets • struct hostent *gethostbyname(char *nom); • struct hostent *gethostbyaddr(const gethostbyaddr(const *addr, int len, int type); char • Para utilizar estas funciones se debe incluir la biblioteca: #include <netdb.h> Otras funciones de sockets struct hostent{ char *h_name; char **h_aliasses; char h_addrtype; g int h_length; char **h_addr_list; }; Otras funciones de sockets struct hostent *host; if((host = gethostbyname(argv[1])) ==-1) 1) //*Error Error al resolver nombre a IP*/ ser.sin_familiy =AF_INET; ser.sin_addr.s_addr = *(long h_addr_list ser.sin_port = htons(1000); *) host-> Sockets • Algunas funciones trabajan en forma bloqueante como accept(), recv(), revfrom(), etc. Para cambiar el modo de trabajo se utiliza la función: int fcntl(int fd, int cmd, long arg) fd = socket(AF_INET, socket(AF INET, SOCKET_STREAM, SOCKET STREAM, 0); fcntl(fd, F_SETFL, O_NONBLOCK); Sockets • La función select permite monitorear un conj nto de descriptores para lectura, conjunto lect ra escritura, y excepciones. int select(int n, fd_set *readfds, fd_set *writefds fd_set *writefds, fd set *exceptfds, *exceptfds timeval *t); • Se utilizan las macros FD_ZERO(), FD_SET(), FD_CLR() y FD_ISSET(); Sockets • Otra alternativa a select es poll, #include <poll.h> int poll(struct pollfd fds[], fds[] nfds_t nfds t n, n int time); struct pollfd { Int fd; Short events;; /*Eventos solicitados*/ Short revents; /*Eventos ocurridos*/ }; Sockets /*Para reutilizar dirección IP*/ int i = 1; setsockopt(s, SOL_SOCKET, SOL SOCKET, 0, &i, sizeof(i)); Sockets Java • Java es un lenguaje multiplataforma que al igual que otros lenguajes de programación tiene APIs para la comunicación de procesos remotos. • La ventaja de utilizar sockets en Java con respecto a su contraparte en C, radica en que Java enmascara la complejidad de los procesos en clases más simples. Sockets Java • Para utilizar sockets y clases similares se necesita utilizar el paquete java.net.*; try { URL loc = “http://www http://www.cursos.com.mx cursos com mx”;; getAppletContext().showDocument(loc); } catch(MalformedURLException e) { System.err.println(“URL inválido”); } Sockets en Java try { URL archivo = new URL(“http://www.itmorelia.edu.mx/lista.txt”); InputStream entrada = archivo.openStream(); DataInputStream datos = new DataInputStream(entrada); String texto; Sockets en Java while( texto = datos.readLine() != null) System.out.println(texto + “\n”); } catch(IOException e) { System.err.println(“Error al leer flujos”); } //Servidor usando sockets stream ServerSocket ss = new ServerSocket(5000, ( 100); Servidor Stream Socket con = ss.accept(); OutputStream sal = con.getOutputStream(); String s = new String(“ITMorelia\n”); for(int i=0; i 0; i < s.length(); s length(); i++) sal.write((int) s.charAt(i)); Conection.close(); () Cliente stream Socket c = new Socket(InetAddress.getLocalHost(), 5000); InputStream entrada = c.getInputStream(); char c; while((c = (char) entrada.read()) != ‘\n’) System.out.println(String.valueOf(c)); Servidor datagramas g try { DatagramSocket sS = new g () DatagramSocket(); DatagramSocket rS = new DatagramSocket( 5000); } catch(SocketException SE) { SE.printStackTrace(); SE printStackTrace(); System.exit(1); } Servidor datagramas g byte a = new byte [100]; DatagramPacket rP = new DatagramPacket( a, g ) a.length); rS.receive(rP); System.out.println(“Dirección:” + rP getAddress() + “ Puerto” + rP.getPort rP.getAddress() rP getPort + “ longitud:” +rP.getLength()); Servidor datagramas g byte d[] = rP.getData(); sP = new DatagramPacket(d, g () 5001); ) rP.getAddress(), d.length, sS send(sendPacket); sS.send(sendPacket); InetAddress comp = InetAddress.getByName(“www.itc.edu.mx”); Sockets Java • Otras excepciones que se pueden capturar: • UnknownHostException • EOFException • ConnectException • Otra forma de implementar la comunicación en grupos es a través de la multidifusión. Cliente datagramas g try { DatagramSocket sS = new g () DatagramSocket(); DatagramSocket rS = new DatagramSocket( 5001); } catch(SocketException SE) { SE.printStackTrace(); SE printStackTrace(); System.exit(1); } Cliente datagrama g try { byte a[] = new byte[100]; DatagramPacket rP rP= new DatagramPacket (a, a.length); rS.receive(rP); byte d[] = rP.getData(); } catch(IOException e) { e.printStackTrace(); } Multicast Java try { I tAdd InetAddress grupo = InetAddress.getByName(args[1]); MulticastSocket s = new MulticastSocket(6789); s.joinGroup(grupo); byte [] m = args[0].getBytes(); DatagramPacket mensajeSalida = new DatagramPacket(m, m.length, grupo, 6789); s.send(mensajeSalida); Multicast Java //conseguir mensajes de otros miembros del grupo byte []buffer = new byte[1000]; for(int i=0; i<3; i++) { DatagramPacket mensajeEntrada = new D t DatagramPacket(buffer, P k t(b ff b buffer.length); ff l th) s.receive(mensajeEntrada); System out println("Recibido: " + new System.out.println("Recibido: String(mensajeEntrada.getData())); } s.leaveGroup(grupo); } catch (Exception e) { //Manejo de excepción} Sockets Java • Algunos componentes gráficos como los JEditorPane pueden ver contenido Web agregando un manejador de eventos. JEditorPane cont = new JEditorPane(); yp ( cont.addHyperlinkListener( new HyperlinkListener() { Public void hiperlinkUpdate(HyperlinkEvent evento) obtenerPágina(evento getUrl toString()); obtenerPágina(evento.getUrl.toString()); } Sockets Java public void obtenerPagina(String ubi) { t { try cont.setPage(ubi); cont setText(ubi); cont.setText(ubi); } catch(IOException e) { JOptionPane showMEssageDialog(this “Error JOptionPane.showMEssageDialog(this, Error al recuperar URL”, “URL incorrecto”, JOptionPane.ERROR_MESSAGE); } } Sockets en Java • Se recomienda la utilización en las nuevas versiones i d Java de J d los de l flujos fl j ObjectInputStream Obj tI tSt y ObjectOutputStream, los cuales son serializables. • El cierre de los flujos debe hacerse en orden inverso de cómo se crearon. crearon • Se pueden cambiar algunas opciones de configuración como s.setSoTimeout(5000); //Tiempo de interrupción de lectura. lectura Sockets Java • También se recomienda el uso de un objeto PrintWriter para manejar de mejor forma la escritura a través de un socket. PrintWriter escritor = PrintWriter(socket.getOutputSream()); escritor println(“Mensaje: escritor.println( Mensaje: ” +mensaje); escritor.flush(); new Sockets Java • Las nuevas versiones de Java permiten la utilización tili ación de sockets sin bloqueo. bloq eo Un servidor sin bloqueo permite atender diversos clientes de manera simultánea sin tener la necesidad de crear un subproceso para atenderlo. • La tecnología sin bloqueos se implementa por medio de SelectableChannel y objetos Selector, ambos usan java.nio.channels; Sockets Java • SelectableChannel representa un canal de comunicación i ió que puede d administrar d i i t varios i canales de E/S en forma simultánea. • Selector es un multiplexor de objetos SelectableChannel permite comprobar los canales SelectableChannel, listos de manera simultánea. • SeverSocketChannel es idéntico a ServerSocket implementando el modo sin bloqueo. bloqueo Sockets Java • También se puede utilizar un objeto Scanner para leer desde un socket. socket Socket s = new Socket( Socket(“time-A time A.timefreq.bldrdoc.gov timefreq bldrdoc gov”, 13); p e = s.getInputStream(); g p (); InputStream Scanner in = new Scanner(e); while(in.hasNextLine()) { String l =in.nextLine(); System.out.println(l); } Sockets Java • Java dispone de otras APIs para servicios de red muy comunes como correo electrónico, Web, etc. Ocupando paquetes como javax.mail.* • Existen otras tecnologías como los Servlets (HttpServlets), Applets y otras tecnologías de objetos distribuidas. WinSocks • Son la implementación de los sockets de Berkele para Windows. Berkeley Windo s Se manejan muy m similar. Se ocupa la biblioteca winsock.lib y las DLLs winsock.dll winsock dll y wsock32.dll wsock32 dll SOCKET s = socket(AF INET socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) /*Error*/ WinSocks HOSTENT *h gethostb name(“ gethostbyname(“www.itmorelia.edu.mx”); itmorelia ed m ”) SOCKADDR_IN ser; memset(&ser, 0, sizeof(SOCKADDR_IN)); ser.sin_family = AF_INET; ser.sin_p port = htons(80); ( ); ser.sin_addr = *((INADDR_IN *) [ ]); >h_addr_list[0]); = h- WinSocks if(connect(s, (SOCKADDR *) &ser, sizeof(ser)) == SOCKET_ERROR) SOCKET ERROR) /*Err*/ send(s, &buf, tam, 0); closesocket(s); • Existen otras APIs de nivel más alto como WinInet ((Windows Internet Service)) WinSocks • Afortunadamente se pueden programar sockets en Windows con un nivel de abstracción más alto utilizando por ejemplo el MFC (Microsoft Solution Framework). • Existe la clase CSocket y CAsyncSocket para comunicaciones síncronas y asíncronas respectivamente. En general se utiliza CAsyncSocket. WinSocks • Algunos métodos de estas clases son: Accept(); OnAccept(); Bind(); Close(); OnClose(); (); OnConnect(); (); Connect(); GetSockOpt(); SetSockOpt(); Listen(); Receive(); OnReceive(); ReceiveFrom(); Send(); OnSend(); SendTo(); Shutdown(); Sockets J2ME Connection web = Connector.open (“http://www.itmorelia.edu.mx”); Connection miSocket = Connector.open ( socket://192.168.1.1:52100 ); (“socket://192.168.1.1:52100”); Connection serial = Connector open Connector.open (“comm:0;baudrate=9000”); Sockets J2ME HttpConnection conn = (Httpconnection) Connector.open(“http://itmorelia.edu.mx”); conn.setRequestMethod (HttpConnection.post); conn.setRequestProperty conn setRequestProperty “GoogleBot”); (“User Agent” (“User-Agent”, Sockets J2ME if (conn.getResponseCode()== HttpConnection HTTP OK) { HttpConnection.HTTP_OK) DataInputStream res = new (conn.openInputStream); byte[] datos = new byte [c.getLength()]; res.readFully(); res close(); res.close(); } else { //Error } DataInputStream Sockets C# • La conexión puede ser síncrona y asíncrona. using System.Net.Sockets; Socket con = new Socket(( Address.Family.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress dir = IPAddress.parse(“127.0.0.1”); p ( ); Sockets C# • IPEndPoint ip = new IPEndPoint(dir, 8090); • con.Bind(ip); • con.Listen(1); • con.Accept(); • con.BeginAccept(new AsyncCallback(onAccept()), con); Sockets C# • Existen objetos conexión: ya predefinidos para WebRequest req = WebRequest.Create(URI) WebResponse resp = req.GetResponse(); req GetResponse(); Stream f = res.GetResponseStream(); StreamReader leer = new StreamReader(f); string cad = leer.ReadToEnd(); Sockets C# • Existen otras clases auxiliares: TcpListener ser = new TcpListener(8000); ser.Start(); TcpClient cli = new TcpClient(); Cli.Connect(new IPEndPoint(serIP, 8000)); Sockets • Estados de una conexión: • Establecida (Enviando, Encolada, Esperando) • Desconexión Recibiendo, 3.3.2 RPC • Las llamadas a procedimientos remotos (RPC) fue el primer intento por obtener un middleware para la construcción de sistemas distribuidos. • Su funcionamiento se basa en la arquitectura cliente/servidor siendo totalmente transparente para el usuario. RPC • El problema del manejo de procesos distribuidos con sockets radica en que se basa en el flujo de E/S, haciendo los programas más difíciles de estructurar. • En 1984 Birelly y Nelson idearon el modelo de RPC a semejanza del llamado de procedimientos locales. RPC • El nivel de transparencia en RPC es muy alto ya que el usuario no tiene que ver con detalles de conexión. • La simplicidad de toda esta heterogeneidad en el llamado a un procedimiento remoto es realizado por los stubs (resguardos) tanto en el cliente como en el servidor. RPC • Para la transferencia de datos entre los stubs, se necesita de un proceso de empacar desempacar los parámetros y resultados. Dicho proceso recibe el nombre de marshalling. • Los stubs se comunican con los núcleos de cada proceso logrando una transparencia muy alta. RPC • La secuencia de mensajes RPC es la siguiente: 1.El procedimiento cliente llama al stub del cliente de la manera usual. 2.El stub del cliente construye un mensaje y hace un señalamiento al núcleo. 3.El núcleo envía el mensaje al núcleo remoto. RPC 4. El núcleo remoto proporciona el mensaje al stub del servidor. 5. El stub del servidor desempaca los parámetros y llama al servidor. 6. El servidor realiza el trabajo y regresa el resultado al stub. 7 El stub del servidor empaca el resultado en 7. un mensaje y hace un señalamiento al núcleo. núcleo RPC 8. El núcleo remoto envía el mensaje al núcleo del cliente. 9. El núcleo del cliente da el mensaje j al stub del cliente. 10.El stub desempaca el resultado y lo regresa al cliente. • El manejo de los datos se hace a través de XDR (eXternal Data Representation). Representation) RPC • Para el envío de datos se utiliza la siguiente forma canónica: Complemento a 2 los enteros, ASCII caracteres, 0 (falso) y 1 verdadero, formato IEEE decimales, todo guardado como little endian. • En la práctica RPC no es lo mismo que un procedimiento local a la hora de revisar los mecanismos de fallas. RPC • La semántica de fallas de RPC es la siguiente: 1.El cliente no puede localizar al servidor. 2.Se pierde el mensaje de solicitud del cliente al servidor 3.Se pierde el mensaje de respuestas del servidor al cliente. 4 El servidor falla antes de recibir una solicitud. 4.El solicitud RPC 5. El cliente falla después de enviar una solicitud. solicitud • En general existen diversas implementaciones de RPC, siendo las más extendidas sobre TCP/IP, la cual tiene los siguientes puntos a favor: • El protocolo ya ha sido diseñado, diseñado lo que ahorra trabajo considerable. RPC • Se dispone de muchas implementaciones. • Esta disponible en casi cualquier c alq ier sistema Unix. • Tanto TCP como UDP están soportados por muchas redes. • Las implementaciones más evolucionadas de RPC incluye la de Sun ONC (Open Network Computing) y DCE (Distributed Computing Environmet). RPC • RPC está desarrollado en C, pero algunas versiones permiten programar en otros lenguajes como Fortran. Las implementaciones más actuales trabajan sobre XML formando los XML-RPC. • Para la conexión entre un cliente y un servidor utilizando RPC se siguen dos pasos: localizar la máquina servidor, y localizar el proceso en esa máquina. RPC • Para encontrar dichos servicios se necesita de un demonio RPC que se encuentre monitoreando todos los procesos remotos, dicho proceso se llama portmap , el cual escucha en el puerto 111. • Muchos servicios de red utilizan RPC para funcionar, entre ellos NFS, el cual es un sistema de archivos distribuidos. RPC • Un programa en RPC se crea a través de un lenguaje de definición de interfaces (IDL por sus siglas en Inglés). Tiene la extension .X program RAND_PROG { version RAND_VER RAND VER { void INICIALIZA_RANDOM(long) =1; ( ) = 2;; doble OBTEN_SIG_RANDOM(void) } =1; /*No. de version*/ } = 0x31111111; /*No. de p programa*/ g RPC • rpcgen -c -a rand.x • • • • • • rand_server.c rand server.c servidor rand_svc.c stub del servidor (no se modifica) rand h cabeceras rand.h rand_clnt.c stub del cliente (no se modifica) rand_client.c cliente rand xdr.c manejo de estructuras rand_xdr.c RPC • 00000000-1FFFFFFF Definidos por sun • 20000000-2FFFFFFF Definidos por el usuario • 40000000-5FFFFFFF Transitorios • 60000000-FFFFFFFF Reservados para usos futuros • rpcinfo -s • portmap RPC const MAX = 100; typedef int Longitud; struct argumentos { float salario; Longitud tam; }; • Sólo se puede recibir y enviar un parámetro. RPC • Existen nuevas propuestas para mejorar el desempeño de RPC como RPC2 que maneja UDP. También se han diseñado mecanismos como MultiRPC para el manejo de RPCs en paralelos. Existen otras alternativas como LRPC (RPC ligeros) que se basan en optimizaciones de la copia de datos y de la planificación de los hilos. • RPC está definido en el RFC 1831. 3.3.3 RMI • La invocación de métodos remotos es la versión orientada i t d a objetos bj t de d la l filosofía fil fí RPC. RPC • L Los programas realizados li d en Java J d b deben h d heredar de la clase remote. • A la hora de ejecutar se deben indicar las políticas de seguridad. seguridad Esto se hace a través del parámetro -D de java RMI java -Djava.security.policy=politica prg • Los archivos de stub se generan con el comando rmic -d . Prg • El primer paso consiste en inicializar el rmiregistry (similar al portmapper en RPC) RMI • Al proxy en el lado cliente se le llama stub, mientrás que en el servidor se le llama skeleton. • Se cuenta con la primitiva invoke(objeto, método, param_entrada, param_salida); • Se necesita de un proceso enlazador (binder) que una a un cliente con el objeto remoto. RMI import java.rmi.*; Import java.util.Vector; public interface Forma extends Remote { int dameVersion() throws RemoteException; GraphicObject dameTodoEstado() throws RemoteException; } RMI public interface ListaForma extends Remote { Forma nuevaForma(GraphicObject g) throws RemoteException; Vector todasFormas() throws RemoteException; int dameVersion() throws ReomteException; } RMI //Sirviente ListaForm import java.rmi.*; import java.rmi.server.UnicastRemoteObject; Iimport java.util.Vector; public class SirvienteListaForma extends UnicastRemoteObject implements ListaForma { private Vector laLista; private int version; RMI public SirvienteListaForma() thorws p {;} RemoteException public Forma nuevaForma(GraphicObject g) thorws RemoteException { version++; F Forma s = new SirvienteForma(g, Si i t F ( version); i ) laLista.addElement(s); return s; //implementar los demás métodos } } RMI • Para acceder al enlazador (RMIRegistry) se utilizan métodos de la clase Naming, utilizando las siguiente URI: • rmi://nombrecompu:puerto/nombreObjeto • Los clientes deben hacer consultas (lookup) a computadoras concretas. Otros métodos son: rebind(), rebind() bind(), bind() unbind() y list(). list() RMI //Programa servidor public class ServidorListaForma { public void main(String args[]){ System.setSecurityManager(new RMISecurityManager()); try { ListaForma unaListaForma SirvienteListaForma(); = new RMI Naming.rebind(“Lista Forma”, unaListaForma); System out println(“Servidor System.out.println( Servidor de ListaForm Listo”); } catch t h (Exception (E ti e)) { System.out.println(“Error: ” +e.getMessage()); } } } RMI //Cliente import java.rmi.*; import java.rmi.server. java.rmi.server.*;; import java.util.Vector; public class ClienteListaForma { public static void main(String args[]) { System.setSecurityManager(new RMISecurityManager()); ListaForma unaListaForma = null; RMI try { unaListaForma = (ListaForma) Naming.lookup(//jcolivares.ListaForma); Vector sLista = unaListaForma.todasFormas(); } catch(RemoteException t h(R t E ti e)) { System.out.println(e.getMessage()); } catch (Exception e) { ;} } } RMI • El marshalling se hace en formato Big-endian. • Jerarquía de clases en RMI: • Object --> RemoteObject RemoteStub, (U i (UnicastRemoteObject) tR t Obj t) (Remote) --> RemoteServer • El puerto por ell cuall escucha h ell RMI es ell 1099 (rmi://localhost:1099/Objeto) RMI • Ejemplo de archivo de política de seguridad: grant { permission java.net.SocketPermission “*:1024-65535”, “connect”; permission java.io.FilePermission “directorio”, “read”; permission java.security.AllPermission; }; 3.3.4 CORBA • Common Object Request Broker Architecture • Es un middleware para la construcción de sistemas distribuidos utilizando el paradigma de programación orientada a objetos. • Una de las principales ventajas de CORBA es que cada uno de los componentes de CORBA se pueden implementar en una gran variedad de lenguajes. CORBA //Ejemplo de IDL en CORBA sstruct uc Persona e so a { string nombre; long año; }; interface ListaPersonas { void añadePersona(in ( Persona p); long damePersona(in string nombre, Persona p); }; out CORBA • CORBA maneja un modelo asíncrono de comunicación, aunque también se puede manejar un esquema de polling. • CORBA utiliza muchas tecnologías estandarizadas como IOR (Interoperable Object Reference), IIOP(Internet Inter ORB Protocol), ORB (Object Request Broker Architecture), entre otras. CORBA • CORBA es una arquitectura genérica, de tal forma que otras tecnologías de objetos como RMI se pueden ejecutar a través de IIOP. • CORBA está basado en una arquitectura de cuatro capas con proxys en el lado cliente y servidor. CORBA • Para realizar objetos remotos en Java se utiliza el Java IDL, IDL el cual está incluido en las diferentes versiones de JDK. • Las interfaces de los objetos remotos se hacen a través del IDL de CORBA. interface Produto { string getDescripcion(); } CORBA • El compilador de IDL a Java se llama idlj o idltojava en versiones antiguas: • idlj Producto.idl • public interface Producto extends org omg CORBA Object org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity CORBA • Los parámetros de los métodos pueden ser in out, in, o t inout. ino t Los parámetros in son por valor, out referencia, inout referencia con valor inicial. inicial • En Java no existen las referencias por lo que se simulan (clases holder). • IDL no soporta sobrecarga de métodos. CORBA • La palabra clave atrribute de IDL hace referencia a métodos set y get module Aplicación { interface producto { attribute string isbn; }; interface Almacen { …}; }; CORBA • Al ejecutar idlj Producto.idl se crean: • Producto.java //definición interfaz • ProductoHolder.java //clase contenedor parametros out • ProductHelper.java // Clase auxiliar • _ProductStub.java //Stub con el ORB CORBA • El mismo ILDL se puede compilar en C++ haciendo uso de la herramienta omniORB, el cual se ejecuta: omniidl –bcxx Producto.idl • El cual genera: • Producto.hh: Producto, Producto_Helper, y POA Producto POA_Producto • ProductoSK.cc implementación CORBA • Para ejecutar el servicio de nombres se corre el programa tnameserv (depreciado) o el orbd con el parámetro –ORBInitialPort 2809 import org.omg. CosNaming. CosNaming.*;; import org.omg.CORBA.*; public class EntCliente { public static void main(String args[]) { try { CORBA ORB orb = ORB.init(args, null); org.omg.CORBA.Object CORBA Obj t n = orb.resolve_initial_references(“NameService” ); NamingContext contexto = NamingContextHelper.narrow(n); NameComponent[] ruta = { new NameComponent(“principal” NameComponent( principal , “Context”) Context ), new NameComponent(“Objeto”, “Object”)}; CORBA org.omg.CORBA.Object obj contexto.resolve(ruta); Objj o = ObjHelper.narrow(obj); j ( j) System.out.println(o.getenv(“PATH”)); } catch (Exception e) { e.printStackTrace(); } } } = CORBA • Para implementar servidor CORBA en java se debe ejecutar idlj –fall archivo.idl import org.omg.CosNaming.*; import org.omg.CORBA. org omg CORBA *;; import org.omg.PortableServer.*; public class SysPropImpl extends SysPropPOA { public String getProperty(String clave) { CORBA return System.getProperty(clave); } } public class ServidorPropSis { public static void main(String args[]) { try { ORB orb = ORB.init(args, null); POA poaraiz = (POA) orb.resolve_initial_references(“RootPOA”); CORBA poaraiz.the_POAManager().activate(); SysPropImpl impl = new SysPropImpl(); org.omg.CORBA.Object ref = poa.raiz.servant_to_reference(impl); org omg CORBA Object org.omg.CORBA.Object objContDenom = orb.resolve_initial_references(“NameService” ); NamingContext contexto = NamingContextHelper narrow(objContDenom NamingContextHelper.narrow(objContDenom ); CORBA NameComponent[] ruta = { new NameComponent(“SysProp”, “Object”)}; Contexto.rebind(ruta, ( ref); ) orb.run(); } catch (Exception e) { e.printStackTrace(System.out); } } } 3.3.5 Servicios Web • Los servicios Web van de la mano de las tecnologías XML. • XML nos sirve para marshalling de los datos. estandarizar el • Utilizar la Web nos permite tener un puerto no bloqueando por Firewall Servicios Web • Son la invocación de código remoto utilizando protocolos estandarizados. estandarizados • En conclusión, realizan la misma función que los sockets, RPC, RMI, Corba y demás tecnologías distribuidas. • Se puede ver a los servicios Web como una analogía de un procedimiento almacenado en una base de datos. Servicios Web • Un servicio Web no es un XML RPC como tal, se diferencia en la forma en que trabajan. • Los servicios Web forman la base de la arquitectura orientada a servicios (SOA) • Los servicio Web utilizan generalmente el método POST de HTTP para enviar los datos de la invocación del servicio. servicio Servicios Web • Los datos viajan envueltos en un protocolo llamado SOAP (Simple (Si l Object Obj t Access A P t l) que hace Protcol) h ell marshalling de los datos. • Una de las principales características que tienen los servicios Web radica en su ubicuidad, ubicuidad ya que pueden ser accedidos desde cualquier sitio, utilizando inclusive cualquier q otro p protocolo de transporte SMTP, FTP, etc. Servicios Web • Los servicios Web necesitan ser descritos (saber que parámetros á t reciben, ib d devuelven) l ) para poderlos d l utilizar en diversos clientes. Esta descripción se realiza a través de WSDL (Web Service Definition Language). • Generalmente esas descripciones los clientes las conocen o bien,, p puede descubrirlas haciendo uso de UDDI (Universal Description, Discovery and Integration). Servicios Web • La UDDI no es otra cosa que un repositorio en donde se almacenan servicios Web que pueden ser invocados por diversos clientes. • Muchas empresas ofrecen servicios Web como amazon, google, http://www.xmethods.com Servicios Web • Ejemplo de archivo WSDL de amazon • <operation operation name name=“AuthorSearchRequest”/> AuthorSearchRequest / • <input message= typens:AuthorSearchRequest /> message=“typens:AuthorSearchRequest”/> • <output message=“typens:AuthorSearchResponse”> • </operation> …. Servicios Web Los tipos de datos se definen en otra parte <xsd:complexType name=“AuthorRequest”> <xsd:all> <xsd:element name=“autor” type=“xsd:string”/> <xsd:element name=“sort” type=“xsd:string” minOccurs=“0”/> </xsd:all> </xsd:complexType> Servicios Web • Cuando se traduce a Java queda: public class AuthorRequest { public AuthorRequest(String author, String page String mode, page, mode String tag, tag String sort, sort String locale, String word, String price) {…} public String getAuthor() {…} { } public String getPage() {…} …. } Servicios Web Para ejecutar el servicio se utiliza: AmazonSearchPort puerto = (AmazonSearchPort) (new AmazonSearchService_Impl().getAmazonSearchP ort()); AuthorRequest solicitud = new AuthorRequest(name, “1” 1 , books, books “”, “lite” lite , “”, token, token “”, “”, “”); ); ProductInfo res= puerto autorSearchRequest(solicitud); puerto.autorSearchRequest(solicitud); Servicios Web • Se ocupa en las versiones viejas el JWSDP (Java Web Service Developer Pack) • Se necesita un archivo config.xml <?xml version=“1.0” encoding=“UTF-8”?> <configuration xmlns=http://java.sun.com/xml/ns/jaxrpc/ri/config> Servicios Web • <wsdl location=“http://soap.amazon.com/schemas3/ AmazonWebServices.wsdl” packageName=“com.amazon” /> • </configuration> • wscompile –import config.xml config xml • wscompile –gen –keep config.xml 3.3.6 Otras tecnologías distribuidas • Entre algunas otras tecnologías distribuidas se encuentra DCOM ((Distributed Componet Object Model) un modelo de programación distribuida usado por Microsoft. • La versión actual de DCOM recibe el nombre de .NET Remoting Services. Otras tecnologías g distribuidas • La finalidad de DCOM es poder realizar módulo disponibles en lenguajes como VB y VC desde cualquier entorno. • Otros ejemplos de tecnologías distribuidas son los agentes móviles como JADE, el código móvil como los Applets, los ActiveX, entre otros. Referencias • Liberty, Jesse, Horvarth, David (200). Aprendiendo C++ para Linux en 21 Días. México, Prentice Hall. • Márquez, Francisco (1994). Unix Programación Avanzada. Estados Unidos, Addison Wesley. Addison-Wesley. Referencias • Colouris, George, Dollimore, Jean, Kindberg, Tim (2001). Sistemas Distribuidos Conceptos y Diseño. 3a. Edición. España, Pearson Addison-Wesley. • Horstmann, Cay, Cornell, Gary (2006). Core Java 2 Volumen II Carácterísticas Avanzadas. España, Perason Prentice Hall. Referencias • Deitel, Harvey, Deitel, Paul (2004). Java Como Programar. Quinta Edición. México, Pearson Prentice Hall. • Márquez, Francisco (2004). UNIX Programación Avanzada. Tercera edición, México, Alfaomega Ra Ra-Ma. Ma. Referencias • Froufe, Agustín, Jorge, Patricia (2004). J2ME Java 2 Micro Mi Editi Edition M Manual l de d usuario i y tutorial. t t i l México, Alfaomega. • Firtman, Maximiliano (2004). Programación de celulares con Java. Java Argentina, Argentina MP Ediciones. Ediciones • Ruíz Ruíz, Diego (2005). (2005) C# La guía programador. Argentina, MP Ediciones. total del Referencias • Tanenbaum, Andrew (2002). Redes de computadoras. Cuarta edición. México, Pearson. • Wigley, Andy, Wheelwright, Stephen (2003). Microsoft .NET Compact Framework. Estados Unidos, Microsoft Press. Referencias • Makofsky, Steve (2004). Pocket PC Network Programming. Estados Unidos, AddisonWesley. • Wall, Kurt (2000). Programación en Linux. Perú, Prentice Hall. • Gregory, Kate (1999). Microsoft Visual C++ 6 España, 6. España Prentice-Hall Prentice Hall Que. Que Referencias • Tanenbaum, Andrew (1996). Sistemas Operativos Distribuidos. México, Prentice Hall. • Tanenbaum, Andrew, Van Steen, Maarten (2006). Distributed Systems Principles and Paradigms. Estados Unidos, Pearson Prentice Hall. Referencias • Vázquez, Adolfo (2002). Alfaomega Ra-Ma. XML. México, ¿ ¿Preguntas? g