Sockets en Java Prof. Wílmer Pereira Universidad Simón Bolívar Arquitectura Cliente/Servidor Request Cliente Servidor Reply ¿ Cómo permitir comunicación entre objetos situados en diferentes máquinas ? Sockets Socketses esuna unaopción opciónpara paramanejo manejode decanales canalesde decomunicación comunicación que queexiste existeen enun unlenguaje lenguajeorientado orientadoaaobjetos objetoscomo comoJava Java La Laidea ideaes esmanejar manejarelelflujo flujodel delcanal canalcomo comoun unarchivo archivo La Laentrada entradaal alcanal canalse semaneja manejacon conlecturas lecturas La Lasalida salidadel delcanal canalcon conescrituras escrituras Identificación del socket AAcada cadasocket socketestá estáasociado asociadoun unnúmero númeroIP, IP, un unnombre nombrede dedominio dominio(DNS) (DNS)yy un unpuerto puerto La clase InetAddress tiene métodos estáticos que que manejan el dominio y el IP, dentro del paquete java.net.InetAddress static static static String String InetAddress getByName(String host) InetAddress[] getAllByName(String host) InetAddress getLocalHost() getHostAddress() getHostName() ... Todas lanza como exception UnknownHostException Ejemplo: Identificación del socket import java.net.*; public class InetAddressTest { public static void main(String[] args) { try { InetAddress Address=InetAddress.getLocalHost(); System.out.println(Address); Address=InetAddress.getByName(“cnn.com”); System.out.println(Address); InetAddress SW[]=InetAddress.getAllByName(“www.nba.com”); for (int i=0;i<SW.lenght;i++) System.out.println(SW[i]); } catch (UnknownHostException e) { System.out.println(“Máquina desconocida (“+e”)”); } } } Identificación de Páginas Web La clase URL permite manejar direcciones que usan los browser. Junto con URLConnection permite acceder a los atributos de una página remota import java.net.*; import java.io.*; import java.Util.Date; class UCDemo { public static void main(String[] args) throw Exception { int c; URL hp=new URL(“http://www.osborne.com”); URLConnection hpCon=hp.OpenConnection(); System.out.println(“Fecha: “+new Date(hpCon.getDate())); System.out.println(“Tipo del Contenido: “+hpCon.getContentType()); int len=hpCon.getContentLenght(); if (len>0) { System.out.println(“=== Contenido ===“); InputStream input=hpCon.getInputStream(); while ((c=input.read())!=-1) { System.out.print((char) c); } input.close(); } else { System.out.println(“No hay contenido disponible”); } } } Cliente Socket La primitiva socket crea el objeto y establece una conexión entre el cliente y el servidor Socket Socket(InetAddress dirIP, int puerto); int getPort(); InetAddress getInetAddress(); ... import java.net.*; import java.io.*; class Whois { public static void main(String[] args) throw Exception { int c; Socket s=new Socket(“internic.net”,43); InputStream in=s.getInputStream(); OutputStream out=s.getOutputStream(); String str=(args.lenght==0?”osborne.com”;args[0]); byte buf[]=str.getBytes(); out.write(buf); while ((c=in.read())!=-1) { System.out.println((char) c); } s.close(); } } Servidor Socket La Laprimitiva primitivaServerSocket ServerSocketcrea creaelelobjeto, objeto,define definelalalista listade deespera espera yyse seenlaza enlazaaaun unpuerto puertobien bienconocido conocido ServerSocket ServerSocket(int puerto) throws IOException; Socket accept () throws IOException; La primitiva accept devuelve un socket que permite manejo concurrente de múltiples clientes Deja libre el puerto bien conocido para la primera conexión de los clientes Debe manejarse con hilos (threads) Ejemplo Servidor (secuencial) import java.net.*; import java.io.*; public class EchoServer { public static void main(String[] args) { try { ServerSocket s=new ServerSocket(8189); Socket ss=s.accept(); BufferedReader in=new BufferedReader (new InputStreamReader(ss.getInputStream())); PrintWriter out=new PrintWriter(ss.getOutputStream,true); out.println(“Hola! Escribir BYE para salir”); boolean done=false; while (!done) { String line=in.readline(): if (line==null) done=true; else { out.println(Echo: “+line); if (line.trim().equals(“BYE”)) done=true; } } ss.close(); } catch (Exception e) { System.out.println(e), } } } Ejemplo Servidor (concurrente) import java.net.*; import java.io.*; public class ThreatedEchoServer { public static void main(String[] args) { int i=1; try { ServerSocket s=new ServerSocket(8189); for (;;) { Socket ss=s.accept(); System.out.println(“Spawning “+i); new ThreadedEchoHandler(ss,i).start(); i++; } } catch (Exception e) { System.out.println(e); } } Programa principal donde se llama al hilo de ejecución de cada cliente Ejemplo Servidor (concurrente) class ThreadedEchoHandler extends Thread { public ThreadedEchoHandler(Socket i, int c) { ss=i; counter=c; } public void run() { try { BufferedReader in=new BufferedReader (new InputStreamReader(ss.getInputStream())); PrintWriter out=new PrintWriter(ss.getOutputStream,true); out.println(“Hola! Escribir BYE para salir”); boolean done=false; while (!done) { String str=in.readline(): if (str==null) done=true; else { out.println(Echo: (“+counter+”): “+str); if (str.trim().equals(“BYE”)) done=true; } } ss.close(); } catch (Exception e) { System.out.println(e), } } private Socket ss; private int counter; } Datagramas Comunicación Comunicaciónno noorientada orientadaaaconexión conexiónpor porlo loque queno noasegura asegura ni nientrega entregade depaquetes paquetesni nirespeto respetoen enelelorden ordende deemisión emisión Más rápido por lo que son una excelente opción en redes de datos muy confiables DatagramSocket DatagramSocket(int puerto); DatagramPacket(byte datos[], int tamaño); int getPort() byte[] getData(); ... Ejemplo de datagrama import java.net*; class WriterServer { public static DatagramSocket ds; public static byte buffer[]=new byte[1024]; public static void main(String[] args) throws Exception { if (args.lenght==1) { ds=new DatagramSocket(777); TheServer(); } else { ds=new DatagramSocket(999); TheClient(); } } public static void TheClient() throws Exception { while (true) { DatagramPacket p=new DatagramPacket(buffer,buffer.lenght); ds.receive(p); System.out.println(new String(p.getData(),0,p.getLenght())); } } Ejemplo de datagrama public static void TheServer() throws Exception { int pos=0; while (true) { int c=System.in.read(); switch (c) { case –1: System.out.println(“Fin”); return; case ‘r’: break; case ‘n’: ds.send(new DatagramPacket(buffer, pos,InetAddress.getLocalHost(),999)); pos=0; break; default: buffer[pos++]=(byte) c; } } } Es de notar que el mismo programa corre para máquinas diferentes sólo siendo diferenciado por un argumento al momento de la llamada Observaciones del enfoque Socket en Java El manejo de la estructura de datos es más sencilla que en la propuesta de sockets para C. Ofrece manejo especializado para conexiones contra servidores HTTP por lo que facilita el desarrollo de aplicaciones Web. A partir de Java 2 se ofrecen primitivas de autentificación para reforzar la seguridad. El paradigma es más sencillo que su competidor en Java RMI