Programación
de Red (TCP/IP) con Java (no multihilos)
La programación de aplicaciones en red con Java es mucho más simple que la
estudiada en C.
El estudio previo sobre la programación orientada a objetos (ELO329) y conceptos de
red (ELO322) son aplicados en esta sección.
El aporte de esta sección es el estudio de las clases de Java para programar
aplicaciones que se comunican a través de la red.
Para estudiar estos ejemplos es recomendable tener a la vista la documentación
del
paquete java.net
Acceso a servidor web vía telnet y
cliente Java simple
Con telnet se puede acceder a cualquier servicio en la red, basta usar la
opción host
seguido
del puerto port:
telnet [-468ELadr] [-S tos] [-b address] [-e escapechar] [-l user] [-n
tracefile] [host [port]]
(vea man telnet por otras opciones)
Si por ejemplo usamos:
% telnet www.elo.utfsm.cl 80
y luego escribimos GET / HTTP/1.0
obtenemos algo como:
En efecto este servidor WEB responde. El mensaje de respuesta depende de
la configuración del servidor. Para recibir una respuesta completa, luego
de GET / HTTP/1.0 agregar una línea con Host: www.electronica.usm.cl
Si deseamos hacerlo vía un programa, sería algo como SocketWebTest.java
Otro ejemplo es la de un cliente conectándose a un servidor de hora basado
en reloj atómico SocketTest.java
Las líneas claves del programaSocketWebTest son:
Socket
s = new Socket("time-A.timefreq.bldrdoc.gov", 13);
BufferedReader in = new
BufferedReader(new InputStreamReader(s.getInputStream()));
La primera crea y abre un socket, el cual es aquí una abstracción para
que el programa pueda comunicarse vía TCP tanto enviando como
recibiendo datos a y desde la máquina y puerto indicados.
Para leer datos desde la conexión, aquí se adapta la entrada de datos del
socket con una instancia de InputStreamReader. Luego usa otra clase
adaptadora -BufferesReader- para mayor eficiencia en la lectura. Con esto
ya se dispone de un objeto sobre el cual podemos leer línea a línea los
datos recibos en el socket.
Otra línea clave es:
PrintWriter
out = new PrintWriter(s.getOutputStream(), true /* autoFlush */);
La cual crea una instancia de PrintWriter,
que es una clase adaptadora para acceder a métodos más cómodos para leer
datos recibidos por el socket.
Cabe notar que los adaptadores BufferedReader y PrinterWriter no son
especiales para la programación de red sino que se pueden usar también
para la lectura y escritura a consola o a otros dispositivos de texto como
archivos. Así también la lectura de datos del socket pudo ser hecha usando
una instancia de Scanner. Ver ejemplo ScannerSocketWebTest.java
el cual implementa el programa equivalente pero usa una instancia se
Scanner para la lectura de datos.
Implementación de un Servidor
En forma análoga al ejemplo visto al inicio de este curso en C, veamos cómo
se codifica un servidor de eco en Java: TCP_EchoServer.java
Para probarlo usted puede correr el cliente
escrito
en C al comienzo de este curso o nuevamente usar telnet.
En el caso de usar el cliente en C, usted notará un desfase porque el
servidor envía un mensaje tan pronto se efectúa una conexión. Esto
desincroniza al cliente.
Notar que la invocación a accept() sobre la instancia de SocketServer se
retorna una instancia de Socket al estilo del cliente visto en los ejemplos
previos: SocketWebTest.java
y SocketTest.java
Cliente/Servidor Simples:
- TCP_EchoServer:
Servidor simple que sólo hace eco de lo enviado por el
cliente.
- TCP_Client:
Cliente muy simple que sólo envía líneas hacia el servidor
y luego lee las líneas enviadas por el servidor.
Ejemplo Cliente/Servidor:
- UDP_EchoServer:
Un servidor mono-hebra que hace eco y muestra por pantalla
los datagramas recibidos agregando IP y puerto origen. Notar que para
atender múltiples clientes no se requiere servidor multi-hebra. Si la
atención de cada requerimiento tomara gran tiempo, es recomendable
atender cada requerimiento a través de una hebra independiente.
- UDP_Client:
Prueba el servidor UDP_EchoServer. Se envian varios mensajes
simple (25 mensajes) y se muestra por pantalla el eco recibido.