Programacion+de+Sockets

**1. Fundamentos**

Los sockets son un sistema de comunicación entre procesos de diferentes máquinas de una red. Más exactamente, un socket es un punto de comunicación por el cual un proceso puede emitir o recibir información.

Los sockets utilizan una serie de primitivas para establecer el punto de comunicación, para conectarse a una máquina remota en un determinado puerto que esté disponible, para escuchar en él, para leer o escribir y publicar información en él, y finalmente para desconectarse. Con todas las primitivas que ofrecen los sockets, se puede crear un sistema de diálogo muy completo.


 *  2. Definición **

Un socket es un punto final de un proceso de comunicación. Es una abstracción que permite manejar de una forma sencilla la comunicación entre procesos, aunque estos procesos se encuentren en sistemas distintos, sin necesidad de conocer el funcionamiento de los protocolos de comunicación subyacentes.



﻿Figura 1. Abstracción del proceso de comunicación entre dos máquinas.

Es así como estos “puntos finales” sirven de enlaces de comunicaciones entre procesos. Los procesos tratan a los sockets como descriptores de ficheros, de forma que se pueden intercambiar datos con otros procesos transmitiendo y recibiendo a través de sockets.

﻿Figura 2. Comunicación entre dos procesos a través de sockets.  Los mecanismos de comunicación entre procesos pueden tener lugar dentro de la misma máquina o a través de una red. Generalmente son usados en forma de cliente-servidor, es decir, cuando un cliente y un servidor establecen una conexión, lo hacen a través de un socket.

**3. Tipos de Sockets**

El tipo de sockets describe la forma en la que se transfiere información a través de ese socket. Existen muchos tipos de sockets, sin embargo, los más populares son:


 * Stream (TCP)
 * Datagram (UDP)
 * Raw (acceso directo al protocolo: root)

 **3.1. Socket Stream**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Son un servicio orientado a la conexión, donde los datos se transfieren sin encuadrarlos en registros o bloques, asegurándose de esta manera que los datos lleguen al destino en el orden de <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px; line-height: 21px;">transmisión. Si se rompe la conexión entre los procesos, éstos serán informados de tal suceso para que tomen las medidas oportunas, por eso se dice que están libres de errores.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">El protocolo de comunicaciones con streams es un protocolo orientado a conexión, ya que para establecer una comunicación utilizando el protocolo TCP (Transmission Control Protocol), hay que establecer en primer lugar una conexión entre un par de sockets. Mientras uno de los sockets atiende peticiones de conexión (servidor), el otro solicita una conexión (cliente). Una vez que los dos sockets estén conectados, se pueden utilizar para transmitir datos en ambas direcciones.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> **3.2. Socket Datagram**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Son un servicio de transporte no orientado a la conexión. Son más eficientes que TCP, pero en su utilización no está garantizada la fiabilidad. Los datos se envían y reciben en paquetes, cuya entrega no está garantizada. Los paquetes pueden ser duplicados, perdidos o llegar en un orden diferente al que se envió.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Las comunicaciones a través de datagramas usan UDP (User Datagram Protocol), lo que significa que, cada vez que se envíen datagramas es necesario enviar el descriptor del socket local y la dirección del socket que debe recibir el datagrama. Como se puede ver, hay que enviar datos adicionales cada vez que se realice una comunicación, aunque tiene la ventaja de que se pueden indicar direcciones globales y el mismo mensaje llegará a un muchas máquinas a la vez.


 * <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px; line-height: 21px;"> 3.3. Socket Raw **

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Son sockets que dan acceso directo a la capa de software de red subyacente o a protocolos de más bajo nivel. Se utilizan sobre todo para la depuración del código de los protocolos.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> **3.4. Diferencias entre Socket Stream y Datagrama**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">El problema aparece al momento de decidir por cual protocolo o tipo de socket usar. La decisión depende de la aplicación cliente/servidor que se esté desarrollando; aunque hay algunas diferencias entre los protocolos que sirven para ayudar en la decisión y utilizar un determinado tipo de socket.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">En UDP, cada vez que se envía un datagrama, hay que enviar también el descriptor del socket local y la dirección del socket que va a recibir el datagrama, luego los mensajes son más grandes que los TCP. Como el protocolo TCP está orientado a conexión, hay que establecer esta conexión entre los dos sockets antes de nada, lo que implica un cierto tiempo empleado en el establecimiento de la conexión, que no es necesario emplear en UDP.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">En UDP hay un límite de tamaño de los datagramas, establecido en 64 kilobytes, que se pueden enviar a una localización determinada, mientras que TCP no tiene límite; una vez que se ha establecido la conexión, el par de sockets funciona como los streams: todos los datos se leen inmediatamente, en el mismo orden en que se van recibiendo.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">UDP es un protocolo desordenado, no garantiza que los datagramas que se hayan enviado sean recibidos en el mismo orden por el socket de recepción. Al contrario, TCP es un protocolo ordenado, garantiza que todos los paquetes que se envíen serán recibidos en el socket destino en el mismo orden en que se han enviado. <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Los datagramas son bloques de información del tipo lanzar y olvidar, es decir, no hay la seguridad de que el paquete llegue o no al destino. Para la mayoría de los programas que utilicen la red, el usar un flujo TCP en vez de un datagrama UDP es más sencillo y hay menos posibilidades de tener problemas. Sin embargo, cuando se requiere un rendimiento óptimo, y está justificado el tiempo adicional que supone realizar la verificación de los datos, la comunicación a través de sockets TCP es un mecanismo realmente útil.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">En resumen, TCP parece más indicado para la implementación de servicios de red como un control remoto (rlogin, telnet) y transmisión de ficheros (ftp); que necesitan transmitir datos de longitud indefinida. UDP es menos complejo y tiene una menor sobrecarga sobre la conexión; esto hace que sea el indicado en la implementación de aplicaciones cliente/servidor en sistemas distribuidos montados sobre redes de área local.

Figura 4. Tipos de socket para el protocolo de Internet

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> **4. Modelo de Sockets**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Como ya se menciono, los sockets extienden el concepto de descriptores de archivos para usarlos en conexiones remotas, en otras palabras, una conexión mediante sockets es idéntica a una comunicación mediante un pipe bidireccional, lo único que cambia es la forma de “abrir” el descriptor de archivo. Las funciones para manipular estos descriptores de archivo se presentan en la tabla 1.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">**5. Funcionamiento Genérico de Sockets**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Como se ha mencionado, la comunicación con sockets hace uso de una serie de primitivas, entre las que destacan socket para establecer el punto de comunicación, connect para conectarse a una maquina remota en un determinado puerto que esté disponible, bind para escribir en él y publicar información, read para leer de él, shutdown o close para desconectarse, entre otras que se hacen mención en la tabla 1. Con todas estas primitivas se puede establecer un sistema de comunicaciones muy completo. En la figura 5 se muestra el funcionamiento de una conexión con sockets.

Tabla 1. Funciones para manipular los descriptores de archivos para conexiones remotas.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> Como se puede observar en la figura 5, un sistema de comunicación necesita de dos entidades bien diferenciadas: el Servidor y el Cliente.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> Normalmente, un servidor se ejecuta sobre una computadora específica y tiene un socket que responde en un puerto específico. El servidor únicamente espera, escuchando a través del socket a que un cliente haga una petición.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> En el lado del cliente: el cliente conoce el nombre de host de la máquina en la cual el servidor se encuentra ejecutando y el número de puerto en el cual el servidor está conectado. Para realizar una petición de conexión, el cliente intenta encontrar al servidor en la máquina servidora en el puerto especificado. Ver figura 6.

Figura 5. Funcionamiento de una conexión socket.



<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Figura 6. Cliente realiza petición de conexión al servidor.



<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Figura 7. Servidor acepta la solicitud y establece la conexión con el cliente.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Si todo va bien, el servidor acepta la conexión. Además de aceptar, el servidor obtiene un nuevo socket sobre un puerto diferente. Esto se debe a que necesita un nuevo socket (y, en consecuencia, un número de puerto diferente) para seguir atendiendo al socket original para peticiones de conexión mientras atiende las necesidades del cliente que se conectó. Ver figura 7.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Por la parte del cliente, si la conexión es aceptada, un socket se crea de forma satisfactoria y puede usarlo para comunicarse con el servidor. Es importante darse cuenta que el socket en el cliente no está utilizando el número de puerto usado para realizar la petición al servidor. En lugar de éste, el cliente asigna un número de puerto local a la máquina en la cual está siendo ejecutado. Ahora el cliente y el servidor pueden comunicarse escribiendo o leyendo en o desde sus respectivos sockets.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">**6. Programación de Sockets en Java**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">La programación utilizando sockets involucra principalmente a dos clases: Socket y DatagramSocket, a la que se incorpora una tercera no tan empleada, ServerSocket, que solamente se utiliza para implementar servidores, mientras que las dos primeras se pueden usar para crear tanto clientes como servidores, representando comunicaciones TCP la primera y comunicaciones UDP la segunda.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">La programación con sockets es una aproximación de bastante bajo nivel para la comunicación entre dos ordenadores que van a intercambiar datos. Uno de ellos será el cliente y el otro el servidor. Aunque la distinción entre cliente y servidor se va haciendo menos clara cada día, en Java hay una clara diferencia que es inherente al lenguaje. El cliente siempre inicia conexiones con servidores y los servidores siempre están esperando que un cliente quiera establecer una conexión. El hecho de que dos ordenadores puedan conectarse no significa que puedan comunicarse, es decir, que además de establecerse la conexión, las dos máquinas deben utilizar un protocolo entendible por ambas para poder entenderse.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">La programación de sockets en el mundo Unix es muy antigua, Java simplemente encapsula mucha de la complejidad de su uso en clases, permitiendo un acercamiento a esa programación mucho más orientado a objetos de lo que podía hacerse antes. Básicamente, la programación de sockets hace posible que el flujo de datos se establezca en las dos direcciones entre cliente y servidor. El flujo de datos que se intercambian cliente y servidor se puede considerar de la misma forma que cuando se guardan y recuperan datos de un disco: como un conjunto de bytes a través de un canal. Y como en todo proceso en el que intervienen datos, el sistema es responsable de llevar esos datos desde su punto de origen al destinatario, y es responsabilidad del programador el asignar significado a esos datos.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Y esto de asignar significado tiene una especial relevancia en el caso de la utilización de sockets. En particular, como se ha dicho, entra entre las responsabilidades del programador la implementación de un protocolo de comunicaciones que sea mutuamente aceptable entre las dos máquinas a nivel de aplicación, para hacer que los datos fluyan de forma ordenada. Un protocolo a nivel de aplicación es un conjunto de reglas a través de las cuales los programas que se ejecutan en los dos ordenadores pueden establecer una conexión e intercambiarse datos.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> **6.1. Java Sockets**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">El paquete java.net de la plataforma Java proporciona una clase Socket, la cual implementa una de las partes de la comunicación bidireccional entre un programa Java y otro programa en la red.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">La clase Socket se sitúa en la parte más alta de una implementación dependiente de la plataforma, ocultando los detalles de cualquier sistema particular al programa Java. Usando la clase java.net.Socket en lugar de utilizar código nativo de la plataforma, los programas Java pueden comunicarse a través de la red de una forma totalmente independiente de la plataforma.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">De forma adicional, java.net incluye la clase ServerSocket, la cual implementa un socket el cual los servidores pueden utilizar para escuchar y aceptar peticiones de conexión de clientes. Por otra parte, si intentamos conectar a través de la Web, la clase URL y clases relacionadas (URLConnection, URLEncoder) son probablemente más apropiadas que las clases de sockets. Pero de hecho, las clases URL no son más que una conexión a un nivel más alto a la web y utilizan como parte de su implementación interna a los sockets.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> **6.2. Modelo de comunicaciones con Java**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">El modelo de comunicaciones más simple es el siguiente:


 * <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px; line-height: 21px;">El servidor establece un puerto y espera durante un cierto tiempo (timeout) a que el cliente establezca la conexión. Cundo el cliente solicite una conexión, el servidor abrirá la conexión socket con el método accept.
 * <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px; line-height: 21px;">El cliente establece una conexión con la máquina host a través del puerto que se designe en el parámetro respectivo.
 * <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px; line-height: 21px;">El cliente y el servidor se comunican con manejadores InputStream y OutputStream. En la figura 8 se puede observar el modelo de comunicaciones descrito.



<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Figura 8. Modelo de comunicación Cliente-Servidor con sockets en Java   <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> **6.3. Apertura de Sockets**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Si estamos implementando un Cliente, el socket se abre de la forma:

<span style="color: green; line-height: 15.9pt; margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm; margin-top: 0cm;">Socket miCliente; <span style="color: green; font-family: 'Courier New'; font-size: 11pt; line-height: 15.9pt; margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm; margin-top: 0cm;">miCliente = new Socket( "maquina", numeroPuerto );

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Donde maquina es el nombre de la máquina en donde estamos intentando abrir la conexión y numeroPuerto es el puerto (un número) del servidor que está corriendo sobre el cual nos queremos conectar. Cuando se selecciona un número de puerto, se debe tener en cuenta que los puertos en el rango 0-1023 están reservados para usuarios con muchos privilegios (superusuarios o root). Estos puertos son los que utilizan los servicios estándar del sistema como email, ftp o http. Para las aplicaciones que se desarrollen, asegurarse de seleccionar un puerto por encima del 1023.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">En el ejemplo anterior no se usan excepciones; sin embargo, es una gran idea la captura de excepciones cuando se está trabajando con sockets. El mismo ejemplo quedaría como:

Socket miCliente; try { miCliente = new Socket( "maquina",numeroPuerto ); } catch( IOException e ) { System.out.println( e ); }

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Si estamos programando un Servidor, la forma de apertura del socket es la que muestra el siguiente ejemplo:

Socket miServicio; try { miServicio = new ServerSocket( numeroPuerto ); } catch( IOException e ) { System.out.println( e ); }

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">A la hora de la implementación de un servidor también necesitamos crear un objeto socket desde el ServerSocket para que esté atento a las conexiones que le puedan realizar clientes potenciales y poder aceptar esas conexiones:

Socket socketServicio = null; try { socketServicio = miServicio.accept; } catch( IOException e ) { System.out.println( e ); }

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> **6.4. Creación de Streams**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> **6.4.1. Streams de Entrada** <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">En la parte Cliente de la aplicación, se puede utilizar la clase DataInputStream para crear un stream de entrada que esté listo a recibir todas las respuestas que el servidor le envíe.

DataInputStream entrada; try { entrada = new DataInputStream( miCliente.getInputStream ); } catch( IOException e ) { System.out.println( e ); }

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">La clase DataInputStream permite la lectura de líneas de texto y tipos de datos primitivos de Java de un modo altamente portable; dispone de métodos para leer todos esos tipos como: read, readChar, readInt, readDouble y readLine. Deberemos utilizar la función que creamos necesaria dependiendo del tipo de dato que esperemos recibir del servidor.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">En el lado del Servidor, también usaremos DataInputStream, pero en este caso para recibir las entradas que se produzcan de los clientes que se hayan conectado:

DataInputStream entrada; try { entrada = new DataInputStream( socketServicio.getInputStream ); } catch( IOException e ) { System.out.println( e ); }

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> **6.4.2. Streams de Salida**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">En la parte del Cliente podemos crear un stream de salida para enviar información al socket del servidor utilizando las clases PrintStream o DataOutputStream:

<span style="color: green; line-height: 14.25pt; margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm; margin-top: 0cm;">PrintStream salida; <span style="color: green; font-family: 'Courier New'; font-size: 10pt; line-height: 14.25pt; margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm; margin-top: 0cm;">try { <span style="color: green; font-family: 'Courier New'; font-size: 10pt; line-height: 14.25pt; margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm; margin-top: 0cm;">salida = new PrintStream( miCliente.getOutputStream ); <span style="color: green; font-family: 'Courier New'; font-size: 10pt; line-height: 14.25pt; margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm; margin-top: 0cm;">} <span style="color: green; font-family: 'Courier New'; font-size: 10pt; line-height: 14.25pt; margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm; margin-top: 0cm;">catch( IOException e ) <span style="color: green; font-family: 'Courier New'; font-size: 10pt; line-height: 14.25pt; margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm; margin-top: 0cm;">{ <span style="color: green; font-family: 'Courier New'; font-size: 10pt; line-height: 14.25pt; margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm; margin-top: 0cm;">System.out.println( e ); <span style="color: green; font-family: 'Courier New'; font-size: 10pt; line-height: 14.25pt; margin-bottom: 0cm; margin-left: 0cm; margin-right: 0cm; margin-top: 0cm;">}

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">La clase PrintStream tiene métodos para la representación textual de todos los datos primitivos de Java. Sus métodos write y println tienen una especial importancia en este aspecto. No obstante, para el envío de información al servidor también podemos utilizar DataOutputStream:

DataOutputStream salida; try { salida = new DataOutputStream( miCliente.getOutputStream ); } catch( IOException e ) { System.out.println( e ); }

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">La clase DataOutputStream permite escribir cualquiera de los tipos primitivos de Java, muchos de sus métodos escriben un tipo de dato primitivo en el stream de salida. De todos esos métodos, el más útil quizás sea writeBytes. <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">En el lado del Servidor, podemos utilizar la clase PrintStream para enviar información al cliente: PrintStream salida;

try { salida = new PrintStream( socketServicio.getOutputStream ); } catch( IOException e ) { System.out.println( e ); }

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Pero también podemos utilizar la clase DataOutputStream como en el caso de envío de información desde el cliente.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;"> **6.5. Cierre de Sockets**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Siempre deberemos cerrar los canales de entrada y salida que se hayan abierto durante la ejecución de la aplicación. En la parte del cliente:

try { salida.close; entrada.close; miCliente.close; } catch( IOException e ) { System.out.println( e ); }

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Y en la parte del servidor:

try { salida.close; entrada.close; socketServicio.close; miServicio.close; } catch( IOException e ) { System.out.println( e ); }

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Es importante destacar que el orden de cierre es relevante. Es decir, se deben cerrar primero los streams relacionados con un socket antes que el propio socket, ya que de esta forma evitamos posibles errores de escrituras o lecturas sobre descriptores ya cerrados.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">**7. Aplicación Cliente-Servidor**

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Para entender de manera práctica los métodos descritos líneas arriba mostraremos una pequeña aplicación cliente-servidor. Primero crearemos un servidor Server.java que atenderá a un cliente. Para hacerlo simple, el servidor sólo le enviará un mensaje al cliente y éste terminará la conexión. El servidor quedará disponible para atender a otro cliente. Es importante saber que, para que el socket funcione, los servicios TCP/IP deben de estar activos, aunque los programas cliente y servidor corran en la misma máquina.

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">A continuación escribiremos el código del servidor que “correrá para siempre”, así que para detenerlo deberá de cortar manualmente la aplicación.

servidor import java.io.*; import java.net.*;

public class Server { public static void main(String argv[]) { ServerSocket servidor; Socket cliente; int numCliente = 0; int PUERTO = 5000; try { servidor = new ServerSocket(PUERTO); do { numCliente++; cliente = servidor.accept; System.out.println("Llega el cliente "+numCliente); PrintStream ps = new PrintStream(cliente.getOutputStream); ps.println("Usted es mi cliente "+numCliente); cliente.close; } while (true); } catch (Exception e)  { e.printStackTrace; } }  }

<span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px;">Ahora vamos a crear la clase Cliente.java que representará al cliente que tan solo establece la conexión, lee a través de un DataInputStream mediante el método readLine lo que el servidor le manda, lo muestra y lo corta.

cliente: <span style="color: #008000; font-family: 'Courier New'; font-size: 10pt; line-height: 14.25pt; margin: 0cm;">import java.io.*; import java.net.*;

public class Cliente { public static void main(String argv[]) { InetAddress direccion; Socket servidor; int numCliente = 0; int PUERTO = 5000; try { direccion = InetAddress.getLocalHost; // dirección local servidor = new Socket(direccion, PUERTO); DataInputStream datos = new DataInputStream(servidor.getInputStream); System.out.println(datos.readLine); servidor.close; } catch (Exception e)  { e.printStackTrace; } }  }


 * <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px; line-height: 21px;">8. Creación de un Chat en Java (Descargar Código) **


 * <span style="font-family: Arial,Helvetica,sans-serif; font-size: 14px; line-height: 21px;">[[file:JavaChat.rar]]﻿ **