Unidad III Primitivas de Sincronización

Anuncio
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 jcolivar@antares.itmorelia.edu.mx
• rsh jcolivar@antares.itmorelia.edu.mx
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
Descargar