Você está na página 1de 58

RMI (REMOTE METHOD

INVOCATION)
Java-RMI (Remote Method
Invocation)
Entorno de invocacin de mtodos remotos disponible en las mquina
virtuales J ava (J VM) (desde la versin 1.1 de J ava)
Provee un modelo de objetos distribuidos similar al de J ava
Objetivo final: conseguir que desarrollo de sistemas distribuidos se
parezca los ms posible al desarrollo de aplicaciones J ava locales
Da soporte a las necesidades tpicas de los sistemas basados en
objetos distribuidos
1. Localizacin de los objetos remotos
RMI contempla 2 mecanismos para obtener referencias a objetos remotos
Registro y localizacin en rmiregistry

(servicio de nombre plano)
Referencias remotas recibidas como parmetro o valor de retorno
2. Comunicacin con los objetos remotos
RMI oculta la comunicacin con los objetos remotos
Para el programador la invocacin de mtodos remotos es idntica a la
invocacin local
3. Carga del cdigo (bytecodes) de los objetos pasados como
parmetro o valor de retorno
RMI proporciona mecanismos para la carga de los datos y el cdigo de los
objetos pasados como parmetro o valor de retorno en las invocaciones
remotas
Permite
Invocar mtodos de objetos remotos
Pasar referencias a objetos remotos como argumento
Dos tipos de objetos en J ava
objeto local: sus mtodos se invocan dentro de su propia
mquina virtual (J VM)
Invocados por el proceso que cre al objeto
objeto remoto: sus mtodos se invocan por procesos
residentes en otras J VMs
La ejecucin si se realiza en su propia J VM
Para que un objeto ofrezca mtodos fuera de su
mquina virtual debe implementar una interfaz remota
Interfaz que extiende java.rmi.Remote
Recoge la declaracin J ava de los mtodos accesibles desde
mquinas virtuales externas
Java-RMI (Remote Method
Invocation)
1
Clientes interaccionan con las interfaces
remotas, no directamente con las clases que
implementan los objetos remotos
Concepto clave: separacin interfaz remoto vs.
implementacin
Modelo basado en el uso de representantes (stubs) por parte
de los clientes
stubs

implementan el mismo interfaz remoto y trasladan las
invocaciones al objeto remoto que las ejecutar realmente
stubs

almacenan y manejan las referencias remotas a los
objetos
El servicio de nombres se encarga de registrar, almacenar y
distribuir esas referencias remotas
Clientes reciben una copia serializada del stub

al hacer
lookup() en el servicio de nombres
Java-RMI (Remote Method
Invocation)
1
Caractersticas generales de
Java RMI
Objeto remoto: Objeto cuyos metodos
pueden invocarse desde otras Mquinas
Virtuales
Descrito por una o ms interfaces remotas en
las que se declaran los mtodos que pueden
ser invocados por objetos de otras J VM
Caractersticas de los objetos
remotos
Las referencias a objetos remotos pueden
pasarse como argumento o valor de retorno en
cualquier invocacin de mtodos (local o
remota)
Las referencias a objetos remotos pueden
convertirse (cast) a cualquiera de los interfaces
remotos que implemente el objeto remoto al que
referencia
El operador instaceof

puede ser usado para
comprobar que interfaces remotos soporta un objeto
Clientes interactan con interfaces remotos,
nunca con las clases de implementacin
directamente
Caractersticas de los objetos
remotos
Objetos remotos deben cumplir ciertas
restricciones adicionales respecto a algunos
mtodos genticos de la clase java.lang.Object
(hashCode(), equals(), clone(), toString())
Normalmente sern subclases de
java.rmi.server.RemoteObject que ya ofrece
implementaciones adecuadas
Mayores posibilidades de fallos en invocaciones
remotas clientes tienen que gestionar nuevos
tipos de excepciones (java.rmi.RemoteException
y derivadas)
Arquitectura de Java RMI
Clientes y servidores. Objetos que implementan la lgica
de la aplicacin
Servidores : crean instancias de los objetos remotos y los
ponen a disposicin de los clientes para recibir peticiones
Crear objetos remotos
Crear referencias remotas y exportarlas
Nombrar y registrar los objetos remotos en el servicio de nombres
Espera de invocaciones
RMI mantiene activo el proceso servidor mientras existan referencias
remotas a alguno de los objetos remotos creados por l (incluidas las
referencias del servicio de nombres)
Cuando un objeto no tiene referencias desde ningn cliente, ni desde
el servidor, queda disponible para la recoleccin de basura (Garbage

Collection)
(a) Estructura Java RMI
Clientes
Declaran objetos de la interfaz remota y obtienen
referencias a objetos remotos (stubs)
Mediante
Consultas al servidor de nombres
Referencias remotas recibidas como valor de retorno
Invocacin de mtodos remotos (mediante el stub)
Un mismo proceso/objeto puede actuar a la
vez como servidor (exporta un objeto remoto)
y como cliente (invoca un mtodo de otro
objeto remoto)
(a) Estructura Java RMI
intercepta las llamadas de los clientes y las
redirecciona al objeto remoto
Objetos locales que actan como
representantes de los objetos remotos
Conocen la localizacin real del objeto remoto
(interfaz RemoteRef)
Direccin IP de la mquina
Identificador nico del objeto (ObjID)
Puerto de escucha de peticiones en la mquina remota
Clase de implementacin del objeto remoto (+ localizacin
de sus bytecodes)
Empaquetan/desempaquetan invocaciones +
argumentos + resultados (mtodo invoke())
Capa de stubs.
interpreta y administra las referencias a objetos remotos
Resuelve las referencias a objetos remotos gestionadas por los
stubs

para acceder e invocar los mtodos de los respectivos objetos
remotos
Responsable de enviar/recibir paquetes empaquetados
(marshalling) con peticiones/respuestas a travs de la capa de
transporte
Internamente, se usa un ObjID

(identificador de objeto) para
identificar los objetos remotos de cada J VM exportados por el
runtime RMI
Cuando se exporta un objeto remoto se le asigna (explcitamente o
implcitamente) una identificacin (gestionada por objetos que
implementan el interfaz java.rmi.server.RemoteRef)
Informacin tpica
Direccin IP de la mquina que ejecuta la J VM
identificador nico del objeto dentro de la J VM
puerto de escucha de la implementacin
Capa de referencias remotas.
Dos alternativas
J RMP (Java Remote Method

Protocol): protocolo
propietario definido por Sun para el manejo de las
referencias remotas y la invocacin de mtodos
Es el usado por defecto
RMI-IIOP (RMI sobre IIOP): usa el protocolo IIOP
(Internet Inter-ORBProtocol) de CORBA para la
comunicacion entre ORBs (Object

RequestBrokers)
(ORB gestiona las referencias remotas entre objetos
CORBA)
Usado en J ava EE (Java Enterprise Edition)
Capa de referencias remotas
1
Capa de transporte.
Ofrece conectividad entre las J VMs
Soporta el intercambio de mensajes entre
stubs

y objetos remotos
Basado en conexiones TCP/IP
(b) Paquetes, clases e interfaces
bsicos
Remote RemoteObject
IOException
RemoteServer
RemoteException
Activatable Unicas1 RemoteObject
Interfaces Interfaces Clases Clases

Implementacin
Extensin
java.rmi
Clases, interfaces y excepciones manejadas tpicamente
por los clientes
Interfaz Remote: interfaz base a
implementar/extender por los objetos remotos
Excepcin RemoteException: base de las
excepciones lanzadas por los objetos remotos
Clase Naming: clase de apoyo para acceder al
servicio de nombres rmiregistry
Clase RMISecurityManager: gestor de seguridad para
aplicaciones RMI
java.rmi.server:
Clases, interfaces y excepciones manejadas tpicamente por los
servidores
Clase RemoteObject: implementacin de mtodos bsicos para objetos
remotos (hashCode(), equals())
Clase RemoteServer: superclase base para las implementaciones de
objetos remotos
Clase UnicastRemoteObject: usada para crear y exportar objetos
remotos con J RMP y obtener un stub

que se comunicar con ese
objeto remoto
Clase RMIClassLoader: cargador de clases (bytecodes) desde orgenes
remotos
necesario para deserializar stubs

y objetos serializados recibidos como
parmetro
Clase ObjID: clase que encapsula un identificador nico para objetos
Clase RemoteStub: superclase de la que heredan las
implementaciones de stubs
Interface RemoteRef, ServerRef: gestin de referencias remotas
java.rmi.registry
Clases, interfaces y excepciones necesarios
para registrar y localizar objetos remotos
Interface Registry: definicin del interfaz
remoto de rmiregistry
Clase LocateRegistry: clase con mtodos
para creacin y consulta de servidores de
nombres
java.rmi.dgc
Clases, interfaces y excepciones para dar
soporte a la recoleccin de basura
distribuida
java.rmi.activation
Clases, interfaces y excepciones para dar
soporte a la activacin de objetos remotos
Clase Activabable: usadas en la creacin y
exportacin de objetos remotos activables
(c) Elementos adicionales
Servicio de nombres. Asocia nombres lgicos a
los objetos remotos exportados (stubs)
Servidor: asocia un nombre al objeto remoto
(registro) [bind()]
Cliente: obtiene una referencia al objeto remoto (stub)
a partir de ese nombre [lookup()]
Objetivo: ofrecer transparencia de ubicacin
Evitar que el cliente tenga que ser recompilado si el
objeto remoto pasa a ejecutarse en otra mquina
virtual (J VM)
Almacena y mantiene asociacin entre j nombre de
objeto remoto referencia remota (stub) serializada
Funcionamiento del proceso bind()
Toma un objeto de la clase que implementa el
interfaz Remote
Si es necesario se construye internamente una
instancia de
RemoteStub para ese objeto
automticamente [J ava 1.5]
desde clase stub

generada por rmic)
Serializa esa instancia de RemoteStub y la
enva al registro asociada a un nombre
En RMI se ofrece el RMIregistry: servidor que
implementa una interfaz de registro/localizacin de
nombres de objetos sencilla
Servidor rmiregistry
Contiene un objeto remoto que implementa el interfaz remoto
java.rmi.registry.Registry
Mtodos:
void bind(String name, Remote obj)
String[] list()
Remote lookup(String name)
void rebind(String name, Remote obj)
void unbind(String name)
Las invocaciones a bind() y lookup() son invocaciones remotas RMI
Por defecto escucha peticiones en el puerto 1099
Debe estar en ejecucin antes de que sean lanzados los
servidores y clientes
Servicio de nombres plano (sin jerarqua)
No persistente (slo mantiene pares
[nombre, objeto] durante la ejecucin del
servidor)
Servidores y clientes acceden al servicio
RMIregistry empleando los mtodos
estticos de las clases java.rmi.Naming
java.rmi.regsitry.LocateRegistry
Clase java.rmi.Naming (implementa java.rmi.registry.Registry)
Clase de conveniencia con mtodos estticos para acceso al
servicio de nombres RMIregistry
Sintaxis de nombrado basada en urls: url://mquina:puerto/nombre
Emplea los mtodos de java.rmi.registry.LocateRegistry
Nota: Existe la posibilidad de utilizar otros servidores de nombres
genricos para almacenar la asociacin (nombre, referencia remota)
empleando el API de J ava J NDI (Java Naming

and

Directory

Interface)
J NDI es independiente de la infraestructura de servicio de
nombrado empleada
Posibilidad de usar servicios de nombres jerrquicos y persistentes
(por ejemplo: servidor LDAP)
Utilizado en la especificacin J ava EE (Java Enterprise Edition)
Ejemplo
Cargador de clases. 1/2
Necesidad de carga dinmica de clases
Cliente debe tener acceso a los bytecodes

(ficheros
.class) de las clases que implementan los stubs

(referencias remotas)
generadas en el servidor (automticamente o mediante rmic)
almacenadas (en forma serializada) junto a su nombre en el
registro RMI
Cliente (y servidor) debe tener acceso a los
bytecodes

(ficheros .class) de las clases cuyos
objetos serializados se pasan como parmetro o
valor de retorno en las invocaciones remotas
Opcin 1. incluir (copiar) esas clases (ficheros
.class) en el CLASSPATH del cliente
Opcin 2. el cargador de clases del cliente las
descargar de forma automtica desde la
localizacin que indique el servidor
Uso de la propiedad java.rmi.codebase

de la J VM:
url apuntando a la localizacin
anlogo al CLASSPATH
$ java -Djava.rmi.codebase=file://directorio_clases/ Servidor
$ java -Djava.rmi.codebase=http://url_clases/ Servidor
$ java -Djava.rmi.codebase=ftp://url_clases/ Servidor
Ese codebase

se almacena en cada clase stub

al ser
serializada para ser incluida en el RMIregistry
Gestor de seguridad 1/2
La necesidad de realizar carga remota de clases
(bytecodes) en RMI abre una potencial brecha
de seguridad.
Posibilidad de carga (y ejecucin) de stubs

malignos
RMI no descargar clases de localizaciones
remotas si no se ha establecido un gestor de
seguridad
RMI ofrece el gestor de seguridad
(java.rmi.RMISecurityManager)
Interpreta e implementa las polticas de seguridad
Permite especificar si se permitir o no realizar una
operacin potencialmente peligrosa antes de realizarla
Establecimiento del gestor de seguridad en el cliente
System.setSecurityManager(new RMISecurityManager());
La poltica de seguridad se configura en un
archivo de propiedades (properties)
Por defecto se utiliza el archivo java.policy incluido en
el J DK
Se puede establecer otra poltica indicando en la
propiedad java.security.policy de la J VM cliente un
archivo properties

distinto
$ java -Djava.security.policy=nueva.policy
EjemploCliente
Ejemplo: archivo nueva.policy
grant {// permite conectar con el puerto 80 (descarga http)
permission.java.net.SocketPermission "*:1024-65535",
"connect,accept"; permission.java.net.SocketPermission
"*:80", "connect";
};
Desarrollo de aplicaciones RMI
Secuencia de pasos tpicos
(1) definir interfaz remoto
(2) crear clase que lo implemente
(3) crear programa servidor
(4) crear programa cliente
(a) Definicin de interfaces
remotos 1/2
Interfaces remotos deben extender directamente o
indirectamente el interfaz java.rmi.Remote
No define mtodos
Sirve como marcador de una clase que define objetos remotos
Definicin de mtodos
Deben declarar la excepcin java.rmi.RemoteException
Los tipos de los parmetros y valor de retorno del mtodo pueden ser
tipos bsicos se pasan por valor (copias serializadas)
objetos locales serializables se pasan por valor (copias serializadas)
objetos remotos se pasan por referencia


cuando cliente invoca mtodo remoto que devuelve referencia a objeto
remoto cliente recibe una instancia de su stub


cuando cliente invoca mtodo remoto pasando referencia a objeto remoto

servidor recibe una instancia de su stub
Slo los mtodos definidos en interfaz remota
estarn disponibles para su invocacin desde
clientes
Ejemplo: Calculadora.java
public interface Calculadora extends java.rmi.Remote
{
int sumar(int a, int b) throws java.rmi.RemoteException;
int restar(int a, int b) throws java.rmi.RemoteException;
int multiplicar(int a, int b) throws java.rmi.RemoteException;
int dividir(int a, int b) throws java.rmi.RemoteException;
int getContadorPeticiones() throws java.rmi.RemoteException;
}
Compilacin: $ javac Calculadora.java
(b) Implementacin del interfaz
remoto 1/2
Clase de implementacin debe de implementar
todos los mtodos definidos en la interfaz
remota
Dos tipos de objetos remotos en RMI
Objetos remotos transitorios. El servidor que los crea y
exporta debe estar en ejecucin durante toda su vida
Residen siempre en memoria
Viven mientras viva el servidor o hasta que el servidor los
destruya
Heredan de UnicastRemoteObject o son exportados con los
mtodos estticos UnicastRemoteObject.exportObject()
Objetos remotos activables. Objetos que tienen
vida independiente del servidor que los crea y
exporta
Slo residen en memoria durante el tiempo en que son
utilizados
Heredan de Activatable o son exportados con
Activatable.exportObject()
Cuando se invoca uno de sus mtodos por un cliente se
activan (vuelven a estar disponibles en memoria)
Se pueden desactivar (salen de memoria pero no se
destruyen) cuando dejan de ser usados por los clientes
Uso de los mecanismos de serializacin para guardar
el estado del objeto en disco al desactivarlo y para
recuperar su estado al activarlo
Finalidad: ahorro de recursos en aplicaciones que
deban gestionar grandes cantidades de objetos remotos
Hacen uso del servidor de objetos activables rmid
Exportacin de objetos remotos
Proceso mediante el que se notifica a la infraestructura RMI la
existencia de un objeto remoto
Objeto remoto queda a la espera de llamadas en un puerto annimo
(> 1024)
Tareas realizadas:
Creacin del puerto de escucha hacia el que el stub

enviar las
peticiones de
Invocacin de mtodos remotos
Creacin de una instancia de un objeto stub

asociado a cada objeto
remoto
automticamente (java 1.5)
a partir de la clase stub

generada con el compilador rmic
El objeto stub

contiene una referencia remota al objeto exportado
refererencia

remota implementa java.rmi.server.RemoteRef y contiene info.
que identifica al objeto de forma nica (dir. IP+puerto+ObjID)
Despus de la exportacin el objeto remoto queda listo para recibir
invocaciones
Objetos remotos transitorios
Hay dos opciones posibles para implementar los objetos
remotos
1. Clase de implementacin extiende
UnicastRemoteObject
Esquema ms sencillo para implementar objetos remotos con RMI
UnicastRemoteObject proporciona todo lo necesario para que un
objeto remoto se integre en la infraestructura RMI
El propio objeto, en su constructor, se exporta a si mismo
(exportacin implcita)
Las instancias de UnicastRemoteObject almacenan referencias a su
propio stub
Importante: hay que definir un constructor de la clase de
implementacion que llame a super() (constructor de
UnicastRemoteObject) para hacer efectiva la auto-exportacin
Adems, ese constructor debe declarar la excepcin
RemoteException
Ejemplo: CalculadoraImpl.java (opcin 1)
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class CalculadoraImpl extends UnicastRemoteObject implements
Calculadora {
private int contadorPeticiones;
public CalculadoraImpl() throws RemoteException {
super();
contadorPeticiones = 0;
}
public int sumar(int a, int b) throws RemoteException {
contadorPeticiones++;
return(a+b);
}
...
}
Compilacion: $ javac CalculadoraImpl.java
2. Clase de implementacin extiende cualquier otra
clase
Se define como una clase normal, nico requisito:
implementar mtodos de interfaz remota
Se usan los mtodos estticos de UnicastRemoteObject
para exportarla explcitamente
Llamados por el servidor que crea el objeto o por el propio
objeto en su constructor o en algn mtodo de inicializacin
propio.
UnicastRemoteObject.exportObject(obj): lo exporta en un puerto
aleatorio
UnicastRemoteObject.exportObject(obj,puerto): lo exporta en el
puerto indicado
Ejemplo: CalculadoraImpl.java (opcin 2)
import java.rmi.RemoteException;
public class CalculadoraImpl implements Calculadora {
private int contadorPeticiones;
public CalculadoraImpl() throws RemoteException {
contadorPeticiones = 0;
}
public int sumar(int a, int b) throws RemoteException {
contadorPeticiones++;
return(a+b);
}
...
Compilacin: $ javac CalculadoraImpl.java
Paso extra: Generacin de clases stub

(y skeleton)
Uso del compilador rmic con el archivo .class de la clase
de implementacin del interfaz remoto
$ rmi CalculadoraImpl (genera CalculadoraImpl_Stub.class)
Slo necesario si los clientes que usarn el objeto
remoto se compilaron con versiones anteriores a J ava
1.5
Desde J ava 1.5 la infraestructura RMI genera los objetos stub

adecuados en tiempo de ejecucin usando los mecanismos de
reflexion de java (API Java Reflection)
(c) Implementacin del
servidor
Tareas tpicas
1. Crear los objetos remotos que implementan
las interfaces remotas
2. Exportar objetos remotos
implcitamente: extienden UnicastRemoteObject
explcitamente: mtodos estticos de UnicastRemoteObj
3. Registrar las referencias a objetos remotos
(los stubs) resultantes de la exportacin en el
servidor de nombres (rmiregistry

) asocandoles
un nombre (mtodos bind(nombre, stub) o
rebind(nombre, stub))
EjemploServidor.java (opcin 1: CaluladoraImpl
extiende UnicastRemoteObject)
import java.rmi.Naming;
public class EjemploServidor {
public static void main(String[] args){
try {
Calculadora calcStub = new CalculadoraImpl();
Naming.rebind("rmi://localhost/Calculadora", calcStub);
System.out.println("Servidor en espera ... ");
}catch (Exception e) {
System.out.println("Error en servidor:"+e);
}
}
}
EjemploServidor.java (opcin 2: CalculadoraImpl no
extiende UnicastRemoteObject)
import java.rmi.Naming;
import java.rmi.server.UnicastRemoteObject;
public class EjemploServidor {
public static void main(String[] args){
try {
Calculadora calc = new CalculadoraImpl();
Calculadora calcStub =
(Calculadora) UnicastRemoteObject.exportObject(calc, 0);
Naming.rebind("rmi://localhost/Calculadora", calcStub);
System.out.println("Servidor en espera ... ");
}catch (Exception e) {
System.out.println("Error en servidor:"+e);
}
}
}
Compilacin: $ javac EjemploServidor.java
(d) Implementacin del cliente
Tareas tpicas
1. Establecer el gestor de seguridad
RMISecurityManager (opcional)
Necesario si se van a utilizar objetos remotos residentes en una
mquina fsica distinta
Establecerlo antes de cualquier invocacion RMI (incluida llamada
a RMIregistry)
System.setSecurityManager(new RMISecurityManager());
2. Obtener las referencias al objeto remoto (stubs)
consultando el servicio de nombres (rmiregistry) (mtodo
lookup(nombre))
3. Invocar los mtodos remotos llamando a los mtodos
del stub

con los parmetros precisos
EjemploCliente.java
import java.rmi.Naming;
public class EjemploCliente {
public static void main(String[] args) {
try {
String urlCalculadora = "rmi://"+args[0]+"/Calculadora";
Calculadora calcStub = (Calculadora)
Naming.lookup(urlCalculadora);
calcStub.sumar(30, 5));
calcStub.restar(30, 5));
calcStub.multiplicar(30, 5));
calcStub.dividir(30, 5));
System.out.println("Contador peticiones: " +
calcStub.getContadorPeticiones());
}catch (Exception e) {
System.out.println("Error: " + e);
}
}
}
Compilacin: $ javac EjemploCliente.java
Pasos para la ejecucin
1. Previamente debe estar en ejecucin el rmiregistry
$ rmiregistry &
2. Lanzar el servidor (quedar a la espera)
$ java EjemploServidor &
Opcional: establecer la propiedad java.rmi.codebase
Necesario si cliente no dispone de los bytecodes
de las clases stub

(o si se usan stub

autogenerados de java 1.5)
de las clases de los parmetros que se intercambian de forma
serializada
Indicar una url

donde estarn disponibles esos
bytecodes

para su descarga por el cargador de clases
del cliente
$ java -Djava.rmi.codebase=file://path_directorio_clases/
EjemploServidor &
3. Lanzar el cliente (en otra mquina o terminal)
$ java EjemploCliente localhost
Opcional: establecer la propiedad
java.security.policy

si la poltica por defecto no
es adecuada (objetos remotos en otra mquina)
$ java -Djava.security.policy=fichero.policy
EjemploCliente host_remoto &
Ejemplo de uso
Para comprender el funcionamiento de los
sockets

no hay nada mejor que estudiar
un ejemplo.
El que a continuacin se presenta
establece un pequeo dilogo entre un
programa servidor y sus clientes, que
intercambiarn cadenas de informacin.
Programa Cliente
El programa cliente se conecta a un
servidor indicando el nombre de la
mquina y el nmero puerto (tipo de
servicio que solicita) en el que el servidor
est instalado.
Una vez conectado, lee una cadena del
servidor y la escribe en la pantalla:
import java.io.*;
import java.net.*;
class Cliente {
static final String HOST = "localhost";
static final int PUERTO=5000;
public Cliente( ) {
try {
Socket skCliente = new Socket( HOST , Puerto );
InputStream aux = skCliente.getInputStream();
DataInputStream flujo = new DataInputStream( aux );
System.out.println( flujo.readUTF() );
skCliente.close();
}catch( Exception e )
{
System.out.println( e.getMessage() );
}
}
public static void main( String[] arg ) {
new Cliente();
}
}
En primer lugar se crea el socket

denominado skCliente,
al que se le especifican el nombre de host

(HOST) y el
nmero de puerto (PORT) en este ejemplo constantes.
Luego se asocia el flujo de datos de dicho socket

(obtenido mediante getInputStream)), que es asociado a
un flujo (flujo) DataInputStream

de lectura secuencial.
De dicho flujo capturamos una cadena ( readUTF() ), y
la imprimimos por pantalla (System.out).
El socket

se cierra, una vez finalizadas las operaciones,
mediante el mtodo close().
Debe observarse que se realiza una gestin de
excepcin para capturar los posibles fallos tanto de los
flujos de datos como del socket.
Programa Servidor
El programa servidor se instala en un puerto
determinado, a la espera de conexiones, a las
que tratar mediante un segundo socket.
Cada vez que se presenta un cliente, le saluda
con una frase "Hola cliente N".
Este servidor slo atender hasta tres clientes, y
despus finalizar su ejecucin, pero es habitual
utilizar bucles infinitos ( while(true) ) en los
servidores, para que atiendan llamadas
continuamente.
Tras atender cuatro clientes, el servidor deja de
ofrecer su servicio:
import java.io.* ;
import java.net.* ;
class Servidor {
static final int PUERTO=5000;
public Servidor( ) {
try {
ServerSocket skServidor = new ServerSocket(PUERTO);
System.out.println("Escucho el puerto " + PUERTO );
for ( int numCli = 0; numCli < 3; numCli++; ) {
Socket skCliente = skServidor.accept(); // Crea objeto
System.out.println("Sirvo al cliente " + numCli);
OutputStream aux = skCliente.getOutputStream();
DataOutputStream flujo= new DataOutputStream( aux );
flujo.writeUTF( "Hola cliente " + numCli );
skCliente.close();
}
System.out.println("Demasiados clientes por hoy");
}catch( Exception e ) {
System.out.println( e.getMessage() );
}
}
public static void main( String[] arg ) {
new Servidor();
}
}
Utiliza un objeto de la clase ServerSocket

(skServidor), que sirve para esperar las
conexiones en un puerto determinado
(PUERTO), y un objeto de la clase Socket

(skCliente) que sirve para gestionar una
conexin con cada cliente.
Mediante un bucle for

y la variable numCli

se
restringe el nmero de clientes a tres, con lo
que cada vez que en el puerto de este servidor
aparezca un cliente, se atiende y se incrementa
el contador.
Para atender a los clientes se utiliza la primitiva accept()
de la clase ServerSocket, que es una rutina que crea un
nuevo Socket

(skCliente) para atender a un cliente que
se ha conectado a ese servidor.
Se asocia al socket

creado (skCliente) un flujo (flujo) de
salida DataOutputStream

de escritura secuencial, en el
que se escribe el mensaje a enviar al cliente.
El tratamiento de las excepciones es muy reducido en
nuestro ejemplo, tan solo se captura e imprime el
mensaje que incluye la excepcin mediante
getMessage().
Ejecucin
Aunque la ejecucin de los sockets

est diseada para trabajar con
ordenadores en red, en sistemas operativos multitarea (por ejemplo
Windows y UNIX) se puede probar el correcto funcionamiento de un
programa de sockets

en una misma mquina.
Para ellos se ha de colocar el servidor en una ventana, obteniendo
lo siguiente:
>java Servidor
Escucho el puerto 5000
En otra ventana se lanza varias veces el programa cliente,
obteniendo:
>java Cliente
Hola cliente 1
>java cliente
Hola cliente 2
>java cliente
Hola cliente 3
>java cliente
connection refused: no further information
Mientras tanto en la ventana del servidor se ha impreso:
Sirvo al cliente 1
Sirvo al cliente 2
Sirvo al cliente 3
Demasiados clientes por hoy
Cuando se lanza el cuarto de cliente, el servidor ya ha
cortado la conexin, con lo que se lanza una excepcin.
Obsrvese que tanto el cliente como el servidor pueden
leer o escribir del socket. Los mecanismos de
comunicacin pueden ser refinados cambiando la
implementacin de los sockets, mediante la utilizacin
de las clases abstractas que el paquete java.net provee.

Você também pode gostar