Paquete Java.net de JAVA

Gran parte de la popularidad de Java se debe a su orientacion a Internet. Cabe añadir que esta aceptacion resulta merecida: Java proporciona una interfaz de sockets orientada a objetos que simplifica muchisimo el trabajo en red.
Con este lenguaje, comunicarse con otras aplicaciones a traves de Internet es muy similar a obtener la entrada del usuario a traves de la consola o a leer archivos, en contraste con lo que sucede en lenguajes como C. Cronologicamente, Java fue el primer lenguaje de programacion donde la manipulacion de la entrada y salida de datos a traves de la red se realizaba como E/S con archivos.
El paquete java.net que proporciona una interfaz orientada a objetos para crear y manejar sockets, conexiones HTTP, localizadores URL, etc., comprende clases que pueden dividir en dos grandes grupos:

  1. Clases que corresponden a las API (interfaces de programacion de aplicaciones) de los sockets: Socket, ServerSocket, DatagramSocket, etc.
  2. Clases correspondientes a herramientas para trabajar con URL: URL, URLConecction, HttpURLConnection, URLEncoder, etc.
El contenido completo de java.net en la J2SE 1.2 es el siguiente:
Clases:
Authenticator
ContentHandler
DatagramPacket
DatagramSocket
DatagramSocketImpl
HttpURLConnection
InetAddress
JarURLConnection
MulticastSocket
NetPermission
PasswordAuthentication
ServerSocket
Socket
SocketImpl
SocketPermission
URL
URLClassLoader
URLConnection
URLDecoder
URLEncoder
URLStreamHandler

Excepciones:
BindException
ConnectException
MalformedURLException
NoRouteToHostException
ProtocoloException
SocketException
UnknownHostException
UnknownServiceException

Interfaces:
ContentHandlerFactory
FileNameMap
SocketImplFactory
SocketOptions
URLStreamHandlerFactory

La jerarquia de clases del paquete java.net se detalla en la siguiente figura:


El paquete java.net permite trabajar con los protocoles TCP y UDP. La clase java.net.Socket permite crear sockets TCP para el cliente; la clase java.net.ServerSocket hace lo mismo par el servidor. Para las comunicaciones UDP, Java ofrece la clase java.net.DatagramSocket para los dos lados de una comunicacion UDP, y la clase java.net.DatagramPacket para crear datagramas UDP.

Read Users' Comments (0)

La clase java.net.ServerSocket

Esta clase es utilizada por el servidor para recibir conexiones d elos clientes media en protocolo TCP. Toda aplicacion que actue como servidor crearar una instancia de esta clase y llamara a su metodo accept(); la llamada hara que la aplicacion se bloquee(esto es, que permanezca esperando) hasta que llegue una conexion por parte de algun cliente. Cuando suceda esto, el metodo accept() creara una instancia de la clase java.net.Socket que usara para comunicarse con el cliente. Nada impide que un servidor tenga un unico objeto ServerSocket y muchos objetos Socket asociados( cada uno a un cliente concreto).
Un objeto ServerSocket es siempre un socket pasivo. En la documentacion de Sun y en muchos libros se consdiera que los ServerSockets son "sockets de servidor". A criterio del autor es na identificacion ambigua: un socket de servidor es un socket que reside en el servidor, ya sea pasivo (ServerSocket) o activo (Socket).
Se usara "socket de servidor" para referirme a un objeto ServerSocket.
Bruce Eckel considera equivoco el termino ServerSocket, pues las clases java.net.ServerSocket y java. net.Socket no estan relacionadas por herencia ni desciendenn de una superclase comun.



Los constructores mas habituales de la clase ServerSocket son estos:
public ServerSocket(int puerto) throws IOException
public ServerSocket(int puerto, int longitudCola) throws IOException
public ServerSocket(int puerto, int longitudCola, InetAddress dirInternet) throws IOException
El argumento puerto es el numero del puerto utilizado por el socket del servidor para escuchar las peticines TCP de los clientes; el entero longitudCola es la longitud maxima de la cola para conexiones entrantes; por ultimo, dirInternet es un objeto InetAddress.
Resulta importante resaltar que la cola de conexiones entrantes es de tipo FIFO (Primero en entrar, primero en salir) y que su longitud maxima viene determinada por el sistema operativo. Es decir: si el argumento longitudCola supera el tamaño maximo de la cola establecida por el sistema operativo, se usara en realidad este ultimo valor sin que se genere ningun aviso para el programador.En el caso de que la cola este llena, el objeto ServerSocket rechazara nuevas conexiones hasta que surjan huecos en ella.
Las instancias de la clase java.net.InetAddress representan direcciones IP. Esta clase no tiene constructores publicos. Para obtener un objeto InetAddress, hay que llamar al metodo estatico byName() con un argumento de tipo String que representa el nombre de un nodo ("www.uv.es", por ejemplo) o una direccion IP ("12.4.234.11", por ejemplo). InetAddress proporciona un metodo -getHostName()- para averiguar el nombre del ordenador local. Los dos siguientes ejemplos serviran para ilustrar el uso de esta clase (el priemro requiere conexion a Internet):


InformarConexionUV.java

Read Users' Comments (0)

La clase java.net.Socket

Esta clase implementa sockets TCP activos (capaces de recibir y transmitir datos).
Sus constructores son:
protected Socket () throws SocketException
protected Socket (SocketImpl impl) throws SocketException
public Socket (String host, int puerto) throws UnknownHostException, IOException
public Socket (InetAddress direccion, int puerto) throws IOException
public Socket (String host, int puerto, InetAddress dirLocal, intpuertoLocal) throws IOException
public Socket (InetAddress direccion, int puerto, InetAddress dirLocal, int puertolocal) throws IOException
public Socket (String host, int puerto, boolean flujo) throws IOException
public Socket (InetAddress host, int puerto, boolean flujo) throws IOException
El constructor public Socket (String host, int puerto) throws UnknownHostException, IOException es uno de los mas usados. Este metodo crea un objeto Socket y loconecta con el puerto con numero puerto de ordenador cuyo nombre es host. En el caso de que se haya instalado algun gestor de seguridad para la maquina virtual Java, se llama al metodo public void checkConnect(String host, int puerto, Object contexto) throws SecurityException, NullPointerException de la clase java.lang.SecurityManager para averiguar si la operacion esta permitida. Si no es asi, se lanza una excepcion java.lang.SecurityException. Si no se puede localizar el ordenador con nombre host, se lanza una excepcion java.net.UnknownException.
No hay que olvidar que el argumento puerto corresponde a la maquina de destino. Generalmente, los programadores no especifican el puerto local vinculado al socket, que es asignado por la maquina virtual Java: la MVJ pregunta al sistema operativo cual es el primer puerto libre y lo usa para el socket. De todos modos, hay dos constructores que permiten especificar el puerto local (puertoLocal). Si no estuviera libre, se lanzaria una excepcion.

Los metodos mas usados de esta clase son:
getInetAddress() :- Devuelve la direccion InetAddress a la cual esta conectado el socket
getPort() :- Devuelve la el numero de puerto al que esta conectado el socket
getLocalAddress() :- Devuelve la direccion local a la cual esta conectado el socket
getLocalPort() :- Devuelve el numero de puerto local al cual esta conectado el socket
getInputStream() :-Devuelve un flujo de entrada para el socket
getOutputStream() :-Devuelve un flujo de salida para el socket
close() :-Cierra el socket

El metodo public InetAddress getInetAddress() devuelve la direccion IP remota( en forma de un objeto InetAddress) a la que esta conectado el socket.
El metodo public int getPort() devuelve el puerto remoto al cual esta conectado el socket.
El metodo public InetAddress getLocalAddress() devuelve la direccion IP remota( en forma de un objeto InetAddress) a la que esta coenctado el socket.
El metodo public int getLocalPort() devuelve el puerto local al cual esta conectado el socket.

El metodo public void close() throws IOException cierra el socket y libera los recursos asociados. Si la operacion no es posible (por ejemplo, porque ya ha sido cerrado), se lanza una excepcion IOException. Al cerrar un socket, tambien se cierran los flujos de entrada y salida asociados.

El metodo public InputStream getInputStream() throws IOException devuelve un flujo de entrada para el socket. Con el, una aplicacion puede recibir informacion procedente de la maquina destino (es decir, del otro lado de la conexion)

El metodo public OutputStream getOutputStream() throws IOException devuelve un flujo de salidad para el socket, que puede usarse para enviar informacion a la maquina de destino (es decir, al otro lado de la conexion).

Para un socket activo, los dos ultimos metodos son imprescindibles: de algun modo debe el socket enviar y recibir datos a traves de la conexion TCP. El paquete java.net recurre al paquete java.io, en concreto a las clases java.io.InputStream y java.io.OutputStream. Estas dos clases tratan los datos como bytes y proporcionan metodos sencillos para leer y escribir bytes y arrays de bytes. Asimismo, sus subclases pueden "envolverse" en clases como java.io.Reader y java.io.Writer, que transmiten datos en forma de caracteres Unicode, no de bytes.
Cuando se trabaj con java.net hay tres clases de java.io que suelen usarse como envoltorio para los objetos devueltos por getOutputStream() y getIntputStrem

  • BufferedReader. los dos metodos mas interesantes para nuestros propositos son read() y readLine(). El priemro devuelve el entero correspondiente al caracter leido ((0 -1 si se ha alcanzado el final del flujo); el segundo devuelve un String que corresponde a una linea de texto. Ambos provocan bloqueo: no terminan de ejecutarse hasta que haya datos disponibles o hasta que se lance una excepcion.
  • PrintStream. Incluye los metodos print() y println() , que permiten enviar datos primitivos y objetos String. El metodo write() permite enviar bytes o arrays de bytes. Los tres metodos bloquean la E/S.
  • PrintWriter. Es una clase similar a la anterios, e incluye tambien los metodos print() y println() . La principal diferencia es que permite enviar caracteres codificados mediante distintas codificaciones (ISO Latin, UTF-8...). Ambos bloquean la E/S.
Ejemplos:

//1 se crea un socket con el nombre del nodo y el numero de puerto 25
Socket socketCliente= new Socket("www.aidima.es", 25);

//2 Se crea un socket con la direccion IP dada y el puerto 25
Socket socketCliente= new Socket("26.56.78.140", 25);

//3 Se crea un socket con la direccion IP dada y el puerto 1025.
Socket socketCliente= new Socket("26.56.78.140", 1025);

//Se obtiene el nombre del ordenador al que pertenece el socket
System.out.println(SocketCliente.getInetAddress());

//Se obtiene el numero de puerto asociado al socket
System.out.println(socketCliente.getPort());

//Una vez establecida la conexion, se extraen los flujos de E/S asociados al socket
InputStream entrada = socketCliente.getInputStream();
OutputStream salida= socketCliente.getOutputStream();

//se lee del servidor un byte mediante el metodo read()
entrada.read();

//se envia al servidor un byte mediante el metodo write()
salida.write(64);

//se usa la clase PrintWriter como envoltorio de OutputStream para enviar una cadena de
//caracteres al flujo de salida. Luego, se cierrra el socket.
PrintWriter pw= new PrintWriter(salida,true);
pw.println("Escribiendo en la salida");
socketCliente.close();
//5 se crea un socket con la direccion IP dada y el puerto 25
Socket socketClietne= new Socket("26.56.78.140", 25);

//una vez establecida la conexion, se extraen los flujos de E/S asociados al socket
InputStream entrada = socketCliente.getInputStream();
OutputStream salida = socketCliente.getOutputStream();

//se usa la clase BufferedReader como envoltorio de InputStream para leer
//lineas completas del flujo de entrada
BufferedReader br= new BufferedReader(new InutStreamReader(SocketCliente.getInputStream()));

//se lee una linea completa y se cierra el socket
br.readLine();
socketCliente.close();

La implementacion de cualquier programa servidor en Java sigue esta secuencia de pasos:

  1. se crea objeto ServerSocket para escuchar a las peticiones que llegan al puerto asociado al servicio
  2. CUando se llama al metodo accetp(), el socket de servidor permanece a la espera de peticiones de clientes por el puerto.
  3. Al llegar una solicitud se siguen tres pasos:
    3.1 Se acepta la conexion, lo cual genera un objeto Socket asociado al cliente
    3.2 Se asocian objetos de las clases contenidas en el paquete java.io a los flujos(streams) de entrada y salida del socket.
    3.3Se lee de los flujos y se escribe en ellos; es decir, se leen y procesas los mensajes entrantes y se envian las respuestas a los clientes.
  4. Se cierran los flujos
  5. Se cierra el socket vinculado al cliente
  6. El socket de servidor continua a la espera de nuevas peticiones

Igualmente los programas cliente se implementan asi:
  1. Se crea un objeto Socket, que tiene asociado un nodo de destino y un puerto donde se ejecuta el servicio de interes
  2. se asocian objetos de las clases cotnenidas en el paquete java.io a loas flujos (Streams) de entrada y salida del socket
  3. se lee de los flujos o se escribe en ellos
  4. se cierran los flujos
  5. se cierra el socket
El cierre de los sockets no debe pasarse por alto: por su naturaleza bidireccional consumen bastantes recursos, tanto de la maquina virtual Java como del sistema operativo.
Un socket se cierra cuando
  • finaliza el programa que lo creo
  • se llama a su metodo close()
  • se cierra uno de los flujos de E/S asociados
  • es eliminado por el recolector de basura
Nota: Si un socket no esta en uso pero permanece abierto no se podra utilizar el puerto local asociado. Una vez cerrado, el sistema operativo podra reutilizar el puerto para otr socket.

Read Users' Comments (0)

Ejemplo de Aplicacion Cliente Servidor con Java.Net

Para mostrar la implementacion en Java de los pasos para escribir aplicaciones cliente-servidor, se incluye este ejemplo:

RegistroConexiones.java
import java.net.*;
import java.io.*;

/**Esta clase envia un breve mensaje a los clientes que se conectan y cierra la conexion. No puede atender a la vez a m as de un cliente . Si hay algun errro al intentar enviar el mensaje al cliente (por ejemplo, porque se ha cerrado tras conectarse), la aplicacion se cierra*/

public class RegistroConexiones{
public static void main(String args[]){
ServerSocket socketServidor=null;
Socket socketCliente=null;
PrintWriter salida=null;
//Se crea el socket de servidor en el puerto 4000
try{
socketServidor= new ServerSocekt(4000);
}
catch(IOException e1){
System.out.println("No se ha podido arrancar el servidor");
//Se intenta cerrar el socket de servidor.
if(socketServidor!=null)
try{
socketServidor.close();
}
catch(IOExceptio e2){
//
}
System.exit(-1);
}
while(true){
try{
//se aceptan peticiones de los clientes
socketCliente=socketServidor.accept();
//se abre un flujo de salida
salida= new PrintWriter(SocketCliente.getOutputStream());
//se muestra informacion sobre la conexion entrante y se envia un mensaje al cliente
System.out.println("Conexion del cliente con direccion" + socketCliente.getInetAddress().getHostAddress()+ "por el puerto" + socketCliente.getPort());
salida.println("Hola y adios");
salida.close();
//se cierra el socket.
socketCliente.close();
}
catch(IOException e3){
if(salida!=null){
salida.close();
}
if(socketCliente!=null){
try{
socketCliente.close();
}
catch(IOE)}
}
}
}

}

Read Users' Comments (0)