Leer y Escribir en un Socket
El siguiente programa es un ejemplo sencillo de cómo establecer una conexión entre un programa
cliente y otro servidor utilizando sockets. La clase Socket del paquete java.net es una
implementación independiente de la plataforma de un cliente para un enlace de comunicación de
dos vías entre un cliente y un servidor. La clase Socket se sitúa en la parte superior de una
implementación dependiente de la plataforma, ocultando los detalles de los sistemas particulares
a un programa Java. Utilizando la clase java.net.Socket en lugar de tratar con código nativo,
los programas Java pueden comunicarse a través de la red de una forma independiente de la
plataforma.
Este programa cliente, EchoTest, conecta con el Echo del servidor (en el port 7) mediante un
socket. El cliente lee y escribe a través del socket. EchoTest envía todo el texto tecleado en
su entrada estandard al Echo del servidor, escribiendole el texto al socket. El servidor repite
todos los caracteres recibidos en su entrada desde el cliente de vuelta a través del socket al
cliente. El programa cliente lee y muestra los datos pasados de vuelta desde el servidor.
import java.io.*;
import java.net.*;
public class EchoTest {
public static void main(String[] args) {
Socket echoSocket = null;
DataOutputStream os = null;
DataInputStream is = null;
DataInputStream stdIn = new DataInputStream(System.in);
try {
echoSocket = new Socket("taranis", 7);
os = new DataOutputStream(echoSocket.getOutputStream());
is = new DataInputStream(echoSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host: taranis");
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: taranis");
}
if (echoSocket != null && os != null && is != null) {
try {
String userInput;
while ((userInput = stdIn.readLine()) != null) {
os.writeBytes(userInput);
os.writeByte('\n');
System.out.println("echo: " + is.readLine());
}
os.close();
is.close();
echoSocket.close();
} catch (IOException e) {
System.err.println("I/O failed on the connection to: taranis");
}
}
}
}
Paseemos a través del programa e investiguemos las cosas interesantes.
Las siguientes tres líneas de código dentro del primer bloque try del
método main() son críticos -- establecen la conexión del socket entre el
cliente y el servidor y abre un canal de entrada y un canal de salida sobre el socket.
echoSocket = new Socket("taranis", 7);
os = new DataOutputStream(echoSocket.getOutputStream());
is = new DataInputStream(echoSocket.getInputStream());
La primera línea de esta secuencia crea un nuevo objeto Socket y lo llama
echoSocket. El constructor Socket utilizado aquí (hay otros tres) requiere
el nombre de la máquina y el número de puerto al que quiere conectarse. El programa de ejemplo
utiliza el host taranis, que es el nombre de una máquina (hipotética) de
nuestra red local. Cuando teclees y ejecutes este programa en tu máquina, deberías cambiar este
nombre por una máquina de tu red. Asegurate de que el nombre que utiliza tienes el nombre IP
totalmente cualificado de la máquina a la que te quieres conectar. El segundo argumento es el
número de puerto. El puerto número 7 es el puerto por el que escucha el Echo del servidor.
La segunda línea del código anterior abre un canal de etnrada sobre el socket, y la tercera
línea abre un canal de salida sobre el mismo socket. EchoTest sólo necesita escribir en el
stream de salida y leer del stream de entrada para comunicarse a través del socket con el
servidor. El resto del programa hace esto. Si no estás familiarizado con los streams de
entrada y salida, podrías querer leer Streams de Entrada
y Salida.
La siguiente sección de código lee desde el stream de entranda estandard de EchoTest (donde el
usuario teclea los datos) una línea cada vez. EchoTest escribe inmediatamente la entada seguida
por un carácter de nueva línea en el stream de salida conectado al socket.
String userInput;
while ((userInput = stdIn.readLine()) != null) {
os.writeBytes(userInput);
os.writeByte('\n');
System.out.println("echo: " + is.readLine());
}
La última línea del bucle while lee una línea de información desde el
stream de entrada conectado al socket. El método readLine() se bloquea
hasta que el servidor haya devuelto la información a EchoTest. Cuando
readline() retorna, EchoTest imprime la información en la salida estandard.
Este bloque continúa -- EchoTest lee la entrada del usuario, la envía al servidor Echo, obtiene
una respuesta desde el servidor y la muestra -- hasta que el usuario teclee un carácter de final
de entrada.
Cuando el usuario teclea un carácter de fin de entrada, el bucle while
termina y el programa continúa ejecutando las siguientes líneas de código.
os.close();
is.close();
echoSocket.close();
Estas línea de código caen en la categoría de limpieza del hogar. Un programa con buen
comportamienteo, se limpia a sí mismo y este programa tiene buen comportamiento. Estas tres
líneas de código cierran las streams de entrada y salida conectados al socket, y cierra la
conexión del socket con el servidor. El orden es importante -- debe cerrar los streams
conectados a un socket antes de cerrar éste.
Este programa cliente tiene un comportamiento correcto y sencillo porque el servidor Echo
implementa un protocolo sencillo. El cliente envía texto al servidor, y el servidor lo devuelve.
Cuando tus programas clientes hablen con servidores más complicados como un servidor http, tu
programa cliente también será más complicado. Si embargo, las cosas básicas son las que has
visto en este programa.
- Abrir un socket.
- Abrir un stream de entrada y otro de salida hacia el socket.
- Leer y escribir a través del socket de acuerdo al protocolo del servidor.
- Cerrar los Streams.
- Cerrar el socket.
Sólo el paso 3 será diferente de un cliente a otro, dependiendo del servidor. Los otros pasos
permanecen inalterables.
También puede ver
java.net.Socket