0% encontró este documento útil (0 votos)
204 vistas24 páginas

Tema 13 - Programación en Java para Red PDF

Este documento describe cómo realizar conexiones de red en Java utilizando URLs y sockets. Explica las clases URL, URLConnection e InetAddress para acceder a recursos remotos mediante URLs y las clases Socket y ServerSocket para establecer comunicaciones entre aplicaciones a través de sockets TCP.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
204 vistas24 páginas

Tema 13 - Programación en Java para Red PDF

Este documento describe cómo realizar conexiones de red en Java utilizando URLs y sockets. Explica las clases URL, URLConnection e InetAddress para acceder a recursos remotos mediante URLs y las clases Socket y ServerSocket para establecer comunicaciones entre aplicaciones a través de sockets TCP.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 24

Programación en Java para Red

Autor: Antonio J. Martín


ÍNDICE

1. INTRODUCCIÓN....................................................................................................... 3

2. URLS......................................................................................................................... 3
2.1. CLASE URL......................................................................................................... 4

2.1.1. Acceso a un documento de texto mediante la clase URL........................... 4

EJERCICIO 1.................................................................................................... 5

2.2. CLASE URLCONNECTION ..................................................................................... 5

2.3. LA CLASE INETADDRESS ...................................................................................... 6

2.3.1. Obtención de un objeto InetAddress ........................................................... 6

2.3.2. Información de un objeto InetAddress......................................................... 7

3. SOCKETS ................................................................................................................. 7
3.1. LA CLASE SOCKET ............................................................................................... 8

EJERCICIO 2.................................................................................................. 10

3.2. LA CLASE SERVERSOCKET ................................................................................. 11

3.2.1. Gestión de conexiones .............................................................................. 11

Ejercicio 3 ....................................................................................................... 12

Ejercicio 4 ....................................................................................................... 15
1. INTRODUCCIÓN
Java proporciona una serie de clases, englobadas en el paquete java.net, que permiten
realizar conexiones entre aplicaciones y transacciones de datos a través de la red.

Utilizando este paquete se pueden comunicar dos o más computadoras que estén
repartidas en distintos puntos del mundo incluso independientemente del tipo de equipo que
sea y de la plataforma utilizada.

La comunicación entre procesos tiene lugar a través de una serie de protocolos


organizados en diferentes capas según el modelo OSI. A nivel de capa de transporte, uno de
los protocolos más populares es el TCP, que es el mayoritariamente empleado en las redes
modernas. Este protocolo es utilizado internamente por las clases de java.net para establecer
la comunicación y realizar la transferencia de datos, liberando al programador de los detalles
específicos de su uso.

En los próximos capítulos vamos a estudiar algunas de las clases más importantes del
paquete java.net, analizando las dos formas principales de establecer comunicaciones entre
aplicaciones en Java: mediante URLs y mediante sockets.

2. URLS
Una URL (Uniform Resource Location) representa la dirección de un recurso dentro de
una red. Toda URL se caracteriza por una cadena de caracteres identificativa que tiene el
siguiente formato:

identificador_protocolo://localización_recurso

En el caso de recursos accesibles a través de la Web, el identificador_protocolo se


refiere al identificador del protocolo empleado en por la capa de aplicación, esto es, http.

En este caso, la cadena identificativa para la localización del recurso tiene el siguiente
formato:

nombre_dominio:protocolo/aplicacion/dir_recurso

Siendo:

ƒ nombre_dominio: El nombre del dominio asociado al servidor donde se


encuentra publicado el recurso, por ejemplo, www.syncrom.com

ƒ protocolo: El protocolo por el que el servidor donde se encuentra publicado el


recurso escucha las peticiones.

ƒ aplicacion. La dirección lógica, dentro del servidor, de la aplicación a la que


pertenece el recurso.

ƒ dir_recurso. Dirección lógica del recurso dentro de la aplicación.

Por ejemplo, la siguiente URL:

http://www.syncrom.com:8080/proyectos/index.html
hace referencia a un recurso de tipo documento HTML que pertenece a la aplicación
“proyectos” que se encuentra publicada en el servidor www.syncrom.com que escucha las
peticiones http por el puerto 8080.

2.1. CLASE URL

Para manejar URLs en aplicaciones Java se utiliza la clase java.net.URL. Su principal


constructor es:

URL (String url)

Con el que podemos construir un objeto URL a partir de la cadena de caracteres que la
identifica.

Entre los métodos más importantes que proporciona esta clase destacamos:

ƒ getPort(). Devuelve el número de puerto de escucha del servidor.

ƒ getHost(). Devuelve el nombre de dominio del servidor.

ƒ getProtocol(). Devuelve el tipo de protocolo asociado a la URL.

ƒ openStream(). Devuelve un objeto de tipo InputStream. Mediante este método


se puede acceder a la información contenida en el recurso. Por ejemplo, en el
caso de un documento HTML podemos utilizar este método para recuperar su
contenido.

ƒ openConnection(). Crea una conexión con el recurso a través de un objeto


URLConnection.

2.1.1. Acceso a un documento de texto mediante la clase URL

A partir del objeto InputStream devuelto por el método openStream() podemos construir
un objeto InputStreamReader que, a su vez, nos permita crear un objeto BufferedReader con el
que poder leer el texto contenido en un recurso remoto de la misma forma en que se realizaba
la lectura de datos de un archivo de texto almacenado en disco.

El siguiente bloque de sentencias nos permitirían crear un objeto BufferedReader con


el que leer el contenido del archivo index.html que indicamos en la URL de ejemplo anterior:

URL url =new URL("http://www.syncrom.com:8080/proyectos/index.html");

BufferedReader bf=new BufferedReader(

new InputStreamReader(url.openStream()));

Hay que tener en cuenta que la creación del objeto URL puede lanzar una excepción
de tipo MalformedURLException si se emplea un protocolo desconocido o la cadena tiene un
formato incorrecto.
EJERCICIO 1

En este primer ejercicio vamos a realizar una aplicación que muestre en pantalla el
contenido de una página de inicio del servidor google.

El código de la clase se muestra en el siguiente listado:

import java.net.*;
import java.io.*;
public class Principal {
public static void main(String[] args){
try{
URL url =new URL("http://www.google.es");
BufferedReader bf=new BufferedReader(new
InputStreamReader(url.openStream()));
String cad="";
while((cad=bf.readLine())!=null){
System.out.println(cad);
}
}
catch(MalformedURLException e){
System.out.println("URL incorrecta");
}
catch(IOException e){
System.out.println("Error en la entrada/salida de
datos");
}
}
}

2.2. CLASE URLCONNECTION

La clase URLConnection es una clase abstracta que representa una conexión a un


recurso apuntado por un objeto URL. Un objeto URLConnection se crea invocando al método
openConnection() del objeto URL, estableciéndose la conexión con el recurso durante la
llamada al método.

Al establecer la conexión con el recurso, el servidor donde éste se encuentra alojado


envía una trama de respuesta a la petición de conexión. Mediante los métodos de
URLConnection se puede acceder a la información contenida en dicha trama:

ƒ getHeaderField(String n). Devuelve el valor del campo de la cabecera de


respuesta cuyo nombre se pasa como parámetro.

Por ejemplo, el siguiente código nos mostraría las cookies enviadas por el
servidor al conectar con la página de inicio de google:
URL url =new URL("http://www.google.es");
URLConnection con=url.openConnection();
System.out.println(con.getHeaderField(“Set-Cookie”));

ƒ getHeaderFieldKey(int i). Devuelve el nombre o clave del campo de cabecera


a partir de su posición.

ƒ getHeaderFields(). Devuelve el número total de campos de cabecera

ƒ getContentType(). Devuelve el contenido de la cabecera Content-Type. Este


campo nos indica el tipo de contenido del recurso.

Además, utilizando los siguientes métodos la aplicación puede interactuar con el


servidor a través de la conexión creada:

ƒ InputStream getInputStream(). Devuelve el InputStream asociado a la


conexión. Se puede emplear este método para recuperar la información del
recurso, al igual que hicimos en el apartado anterior con el método
openStream() de la clase URL.

ƒ OutputStream getOutputStream(). Devuelve el OutputStream asociado a la


conexión. A través de este objeto, podemos enviar datos al recurso del
servidor en caso de que se trate de una aplicación.

2.3. LA CLASE INETADDRESS

Un objeto InetAddress representa la dirección IP o nombre de dominio asociada a una


máquina. La dirección IP es un número identificativo de 32 bits que se utiliza como identificador
de los equipos que se comunican en una red mediante protocolo IP, este protocolo es de nivel
inferior a TCP y UDP, así, cuando hablamos de redes TCP/IP nos referimos a aquellos
sistemas de comunicación que utilizan ambos protocolos (IP en el nivel de red y TCP en el de
transporte), como es el caso de las redes Internet.

2.3.1. Obtención de un objeto InetAddress

La clase InetAddress no dispone de constructores públicos que permitan crear objetos


de la forma estándar, debiendo recurrir a los siguientes métodos estáticos incluidos en la
misma:

ƒ static InetAddress getByName(String host). Devuelve un objeto


InetAddress que representa la dirección IP correspondiente al host (ordenador)
pasado como parámetro. El parámetro puede ser el nombre del host
(“www.syncrom.com”) o su dirección IP como cadena de caracteres
(“156.23.45.8”).

ƒ static InetAddress[] getByAllName(String host). Devuelve un array de


InetAddress correspondiente a todas las direcciones IP asociadas al host cuyo
nombre se suministra como parámetro.

ƒ static InetAddress getLocalHost(). Devuelve la dirección IP del ordenador en


el que se está ejecutando la aplicación.

Los tres métodos anteriores lanzarán una excepción UnknowHostException en caso de


que no se pueda encontrar el host o máquina cuyo nombre se indica. En el caso de
getLocalHost(), la excepción se producirá si no se puede encontrar una IP para la máquina
local.
2.3.2. Información de un objeto InetAddress

Además de los métodos anteriores orientados a la creación de objetos InetAddress,


esta clase dispone de otros métodos no estáticos que nos permiten obtener información del
objeto. Entre ellos destacan:

ƒ String getHostName(): Devuelve el nombre de host del objeto InetAddress al


que se aplica.

ƒ String getCanonicalHostName(). Devuelve el nombre cualificado completo


del host asociado.

ƒ String getHostAddress(): Devuelve la dirección IP como un String.

ƒ byte[] getAddress(): Devuelve los componentes de la dirección IP como un


array de bytes.

El siguiente programa de ejemplo nos mostraría en pantalla todos los datos asociados
al servidor Web de Syncrom:

import java.net.*;
public class Principal {
public static void main(String[] args) throws
UnknownHostException{
InetAddress dir=
InetAddress.getByName("www.syncrom.com");
System.out.println("nombre host :"+dir.getHostName());
System.out.println("nombre host completo "+
dir.getCanonicalHostName());
System.out.println("dir ip "+dir.getHostAddress());
for(int i=0;i<dir.getAddress().length;i++){
System.out.println(dir.getAddress()[i]);
}
}
}

3. SOCKETS
Un socket representa el punto de conexión utilizado por un proceso para comunicar con
otro proceso a través de una red TCP o UDP.

Según cuál de estos protocolos se utilice, distinguiremos entre dos tipos de sockets:

ƒ Sockets Stream (TCP). El protocolo TCP está orientado a conexión, lo que


significa que, para establecer una comunicación entre los procesos hay que
establecer primero una conexión entre los sockets. Uno de los sockets es el
que solicita la conexión (cliente) y el otro el que la atiende (servidor). Cuando
los sockets están conectados, se pueden utilizar para transmitir datos en
ambas direcciones, mientras la conexión continúe las dos aplicaciones se
estarán comunicando utilizando un flujo de datos continuo.
ƒ Sockets Datagrama (UDP). La información se envía en paquetes. El transporte
se realiza sin establecer una conexión previa. Son más eficientes pero menos
fiables que los Sockets Stream.

El paquete java.net incorpora las clases Socket, DatagramSocket y ServerSocket para


la gestión de sockets. Las dos primeras permiten crear tanto procesos cliente como servidor;
Socket se emplea en comunicaciones basadas en TCP, mientras DatagramSocket lo hace con
UDP. Por su parte, ServerSocket se únicamente para implementar servidores.

3.1. LA CLASE SOCKET

La clase Socket se utiliza habitualmente para crear sockets a nivel de aplicación cliente
utilizando el protocolo TCP. La comunicación a través de este tipo de socket requiere que se
indique la localización de la máquina con la que se establecerá la conexión y el puerto de la
misma por el que se producirá la comunicación.

Equipo: xxx

Puerto n

Aplicación
cliente
socket
Host:xxx
Puerto:n

Figura. 1.

Para crear un objeto Socket utilizaremos los siguientes constructores de la clase:

ƒ Socket (InetAddress dir, int puerto): Crea un socket a partir de un objeto


InetAddress y un puerto de comunicaciones. La utilización de este constructor
puede generar una excepción de tipo IOException que habrá que controlar.

ƒ Socket (String host, int puerto): Crea un socket con un nombre de host y en
un puerto específico. Además de IOException, este constructor puede lanzar
una excepción UnknownHostException en caso de que no exista el nombre de
host indicado.

Una vez definido el socket, el intercambio de datos entre la aplicación y el punto de


comunicación definido se lleva a cabo a través de los siguientes métodos de la clase:

ƒ InputStream getInputStream(). Devuelve un objeto del tipo InputStream que


representa el flujo de entrada asignado a ese Socket. Utilizando la clase
BufferedReader se podrá leer información procedente de este host remoto.

ƒ OutputStream getOutputStream(). Devuelve un objeto OutputStream con el


flujo de salida asociado al socket. Utilizando la clase PrintWriter se podrá
enviar información al host remoto.
El siguiente bloque de código corresponde a un programa que se encarga de mostrar
en pantalla la página de inicio generada por un determinado servidor http, para ello, establece
una conexión mediante un socket con el servidor a través del puerto 80 y lanza una petición
GET a través del stream de salida. La respuesta generada por el servidor es recibida en el
stream de entrada:

import java.net.*;
import java.io.*;
public class Test {
public static void main(String[] args) throws
UnknownHostException, IOException {
String url="java.sun.com";
int puerto =80;
Socket sc=new Socket(url, puerto);
BufferedReader bf=new BufferedReader(
new InputStreamReader(sc.getInputStream()));
PrintWriter out=new PrintWriter(
sc.getOutputStream(),true);
out.println("GET /");
String s=null;
while((s=bf.readLine())!=null){
System.out.println(s);
}
}
}

Además de los anteriores, la clase Socket dispone de una serie de métodos que nos
permiten obtener información sobre el mismo:

ƒ getInetAddress(): Devuelve un objeto InetAddress que representa la dirección


a la cual el Socket está conectado.

ƒ getLocalPort(): Devuelve el número de puerto local al que está asignado el


socket.

ƒ getPort(): Devuelve el puerto remoto donde se ha conectado el socket.

Una vez finalizado el intercambio de datos entre una aplicación y el punto final
representado por el socket, se debe proceder al cierre del mismo a fin de liberar los recursos
utilizados, operación esta que se lleva a cabo a través del método close() de la clase Socket.

Hay ocasiones en las que a la hora de enviar información por un socket a través del
stream de salida los datos no llegan hasta el punto final mientras el socket esté abierto. En este
caso podemos recurrir al método flush() del objeto PrintWriter utilizado para la escritura, el cual
realiza el vaciado del stream provocando que los datos lleguen de forma inmediata a su
destino.
EJERCICIO 2

En este ejercicio se va a desarrollar una aplicación que enviará una cadena de texto al
puerto de eco (puerto nº 7) de un servidor a través de un socket; dado que se trata del puerto
de eco, el servidor devolverá inmediatamente la cadena recibida, la cual se mostrará en
pantalla.

Hay que tener en cuenta que este programa no funcionará si el equipo contra el
queremos conectarnos dispone de un cortafuegos que impida el acceso al puerto de eco.

El código de la aplicación se muestra en el siguiente listado:

import java.net.*;
import java.io.*;
public class Eco {
public static void main(String[] args) {
String url="java.sun.com";
int puerto=7;
try{
Socket sc=new Socket(url,puerto);
//objeto para lectura del teclado
BufferedReader bfteclado=new BufferedReader(
new InputStreamReader(System.in));
//objeto para lectura de los datos recibidos
//del servidor a través del socket
BufferedReader bfsocket=new BufferedReader(
new InputStreamReader(sc.getInputStream()));
//envía al servidor los datos introducidos
//por teclado
PrintWriter out=new PrintWriter(
sc.getOutputStream(),true);
System.out.println("escribe un texto");
out.println(bfteclado.readLine());
out.flush();
//muestra la respuesta del servidor
System.out.println("Eco devuelto por servidor: "+
bfsocket.readLine());
sc.close();
}
catch(UnknownHostException e){
System.out.println("El host indicado no existe");
}
catch(IOException e){
System.out.println("Error en la entrada/salida de
datos");
}
}
}

3.2. LA CLASE SERVERSOCKET

La clase ServerSocket permite crear un servidor de comunicaciones capaz de aceptar


múltiples usuarios o clientes; dicho servidor queda definido por el host donde se ejecuta la
aplicación y el puerto por el que espera recibir las peticiones de los clientes.

El objeto ServerSocket está pensado para implementar procesos que se encuentren


permanentemente a la espera de recibir peticiones por parte de aplicaciones clientes. Cada vez
que se recibe una aplicación se conecta mediante un socket al host y puerto definido por
ServerSocket, este devuelve un objeto Socket que permite comunicar con la aplicación cliente.

Para crear un objeto ServerSocket puede utilizarse cualquiera de los siguientes


constructores:

ƒ ServerSocket(int puerto): Crea un socket del servidor asociado a un


determinado puerto. Se aceptan como máximo 50 clientes.

ƒ ServerSocket(int puerto, int maximo): Se indica además el número máximo


de clientes que pueden conectarse. Si llegan más clientes serán rechazados.

La creación de un socket del servidor con cualquiera de estos constructores puede


provocar una excepción de tipo IOException que habrá que capturar.

3.2.1. Gestión de conexiones

Como decíamos anteriormente, una vez creado el socket de servidor el objeto queda
preparado para recibir conexiones a través del puerto indicado. La llamada al método accept()
de ServerSocket bloquearía la aplicación hasta recibir una conexión, momento en el cual
accept() devolvería un objeto Socket asociado a dicha conexión.

Utilizando este objeto socket la aplicación del servidor puede enviar y recibir
información hacia/desde la aplicación cliente.

El siguiente bloque de instrucciones de ejemplo crearía un socket del servidor que se


mantendría indefinidamente a la espera de recibir peticiones en el puerto 1000; cada vez que
recibe una petición, pasará el socket generado a un método de procesamiento de petición:

ServerSocket servidor = new ServerSocket(1000);

Además de accept(), la clase ServerSocket proporciona los siguientes métodos para la


gestión de las conexiones:

ƒ close(). Cierra la conexión.

ƒ isClosed(). Indica si el socket está o no cerrado.

ƒ getLocalPort(). Obtiene el puerto por el que el socket del servidor está


escuchando.
ƒ getInetAddress(). Devuelve el objeto InetAddress asociado a este socket de
servidor.

Ejercicio 3

En esta práctica vamos a desarrollar una aplicación de comunicación entre procesos


cliente y servidor a través de sockets.

Por un lado crearemos una aplicación de servidor que utilizará un objeto ServerSocket
para recibir las peticiones por parte de los procesos cliente. Cada vez que se reciba una
petición, este proceso recuperará la información enviada por el cliente y se le enviarán a través
de la conexión creada diez mensajes de texto en el que se le indique el número de orden que
hace su petición en el conjunto total. Para que el proceso servidor pueda atender múltiples
solicitudes clientes de forma simultánea, cada petición será atendida por un hilo diferente.

Por otro lado, el desarrollo del proceso cliente consistirá en una aplicación de consola
que se encargará de conectar con el servidor y pasarle una cadena de texto solicitada al
usuario, así como de mostrar en pantalla la respuesta generada por el servidor.

El siguiente listado corresponde a la clase encargada de iniciar la ejecución del proceso


del servidor:

package servidor;
import java.net.*;
import java.io.*;
public class IniciarServidor {
public static void main(String[] args) {
int puerto=3000;
int orden=1;
try{
ServerSocket servidor=new ServerSocket(puerto);
while(true){
System.out.println("Esperando petición...");
//cuando recibe una petición desde un cliente
// crea un hilo para atenderlo, pasándole el
// socket que representa la conexión con
//el cliente
Socket con=servidor.accept();
(new ProcesaConexion(con,orden)).start();
orden++;
}
}
catch(UnknownHostException e){
System.out.println("El host indicado no existe");
}
catch(IOException e){
System.out.println("Error en la entrada/salida de
datos");
}
}
}
La clase del servidor encargada de procesar las peticiones clientes se muestra en el
siguiente listado:

package servidor;

import java.net.*;
import java.io.*;
public class ProcesaConexion extends Thread{
Socket sc;
int orden;
public ProcesaConexion(Socket sc, int orden){
this.sc=sc;
this.orden=orden;
}
public void run(){
try{
PrintWriter out=new
PrintWriter(sc.getOutputStream());
BufferedReader bf=new BufferedReader(new
InputStreamReader(sc.getInputStream()));
//recupera la cadena enviada por el cliente
//al establecer la conexión
String nombre=bf.readLine();
//envia 10 mensajes al cliente indicandole su orden
//en el conjunto de peticiones recibidas
for(int i=1;i<=10;i++){
out.println("mensaje "+i+
" para el cliente "+
nombre+": Su número de orden es "+orden);
out.flush();
Thread.sleep(200);
}
sc.close();
}
catch(IOException e){
System.out.println("Error en la entrada/salida de
datos");
}
catch(InterruptedException e){
e.printStackTrace();
}
}
}
Finalmente, el proceso cliente será implementado por la siguiente clase:

package cliente;
import java.net.*;
import java.io.*;
public class IniciarCliente {
public static void main(String[] args) {
int puerto=3000;
String mensaje=null;
try{
Socket conexion=new Socket("localhost",puerto);
PrintWriter out=new PrintWriter(
conexion.getOutputStream(),true);
//solicita un dato al cliente
BufferedReader lectorteclado=new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Introduce tu nombre");
//envía el dato solicitado al servidor
out.println(lectorteclado.readLine());
out.flush();
//recupera la respuesta generada por el servidor
//al enviarle el dato y la muestra en pantalla
BufferedReader lectorsocket=new BufferedReader(
new InputStreamReader(conexion.getInputStream()));
while((mensaje=lectorsocket.readLine())!=null){
System.out.println("Mensaje recibido "+mensaje);
}
conexion.close();
}
catch(UnknownHostException e){
System.out.println("El host indicado no existe");
}
catch(IOException e){
System.out.println("Error en la entrada/salida de
datos");
}
}
}
Ambos procesos (cliente y servidor) pueden ejecutarse en la misma máquina. De
hecho, como se puede apreciar en los listados anteriores, cada uno tiene su propia clase main.
Para simular el funcionamiento concurrente con múltiples clientes, la clase IniciarCliente deberá
ejecutarse tantas veces como cliente se quieran generar.

Ejercicio 4

Vamos a desarrollar una nueva aplicación práctica de comunicación entre procesos a


través de sockets. En este caso, crearemos un programa que permita a las tiendas de una
determinada firma enviar la cifra de ventas diaria a un proceso central, utilizando para ello una
interfaz gráfica como la que se indica en la figura 2.

Figura. 2.

El proceso central recogerá los datos de cada tienda y almacenará la información en un


fichero de texto. Por cada solicitud recibida, el servidor añadirá una línea en el fichero de texto
con el siguiente formato:

Identificador_tienda|cantidad|fecha|host_cliente

Las siguientes listados corresponden a las clases del proceso cliente:


package cliente;
import java.net.*;
import java.io.*;
public class IniciarCliente {
public static void main(String[] args) {
Interfaz ventana=new Interfaz("Envio de ventas",
100,100,600,400);
}
}

package cliente;
import javax.swing.*;
import java.awt.event.*;
public class Interfaz extends JFrame implements ActionListener{
JTextField jtxtid,jtxtcant;
public Interfaz(String title, int x, int y, int w, int h){
super(title);
this.getContentPane().setLayout(null);
this.setBounds(x, y, w, h);
//controles para introducción de identificador
JLabel jlbid=new JLabel("Identificador de tienda");
jlbid.setBounds(100, 100, 160, 30);
this.getContentPane().add(jlbid);

jtxtid=new JTextField();
jtxtid.setBounds(240, 100, 50, 25);
this.getContentPane().add(jtxtid);
//controles para introdución de cantidad
JLabel jlbcant=new JLabel("Cantidad vendida");
jlbcant.setBounds(100, 180, 160, 30);
this.getContentPane().add(jlbcant);

jtxtcant=new JTextField();
jtxtcant.setBounds(240, 180, 50, 25);
this.getContentPane().add(jtxtcant);
//botón enviar
JButton bt=new JButton("Enviar");
bt.setBounds(150,260, 120, 40);
this.add(bt);
//asociación con el manejador de evento
bt.addActionListener(new ProcesarEnvio(this));
//botón salir
JButton btsalir=new JButton("Salir");
btsalir.setBounds(280,260, 120, 40);
this.add(btsalir);
//asociación con el manejador de evento
btsalir.addActionListener(this);
this.setVisible(true);
}

public void actionPerformed(ActionEvent e) {


this.dispose();
}
}

package cliente;

import java.net.*;
import java.io.*;
import javax.swing.*;
import java.awt.event.*;
public class ProcesarEnvio implements ActionListener{
private Interfaz ventana;
public ProcesarEnvio(Interfaz ventana){
this.ventana=ventana;
}
public void actionPerformed(ActionEvent e){
//recupera los datos de los campos de texto
//y monta la primera parte de la cadena
String identificador=this.ventana.jtxtid.getText();
String cantidad=this.ventana.jtxtcant.getText();
String datoenvio=identificador+"|"+cantidad+"|";
String host="localhost";
int puerto=3000;
//conecta con el servidor y le envía la cadena
//con el identificador y la cantidad
try{
Socket conexion=new Socket(host,puerto);
PrintWriter out=new PrintWriter(
conexion.getOutputStream(),true);
out.println(datoenvio);
out.flush();
out.close();
}
catch(UnknownHostException ex){
System.out.println("El host indicado no existe");
}
catch(IOException ex){
System.out.println("Error en la entrada/salida de
datos");
}

}
}

En cuanto al proceso de servidor, las clases IniciarServidor y ProcesaConexion


corresponden a la generación del socket del servidor y a la gestión de peticiones,
respectivamente. He aquí el código de las mismas:

package servidor;
import java.net.*;
import java.io.*;
public class IniciarServidor {

public static void main(String[] args) {


int puerto=3000;
String url_fichero="datos_ventas.txt";
FileWriter fichero=null;
try{
fichero=new FileWriter(url_fichero, true);
ServerSocket servidor=new ServerSocket(puerto);
while(true){
System.out.println("Esperando petición...");
//cuando recibe una petición desde un cliente
// crea un hilo para atenderlo, pasándole el
// socket que representa la conexión con
//el cliente
Socket con=servidor.accept();
(new ProcesaConexion(con,fichero)).start();
}
}
catch(UnknownHostException e){
System.out.println("El host indicado no existe");
}
catch(IOException e){
e.printStackTrace();
System.out.println("Error en la entrada/salida de
datos");
}
finally{
try{
fichero.close();
}
catch(IOException e){}
}
}
}

package servidor;

import java.net.*;
import java.io.*;
import java.util.*;
public class ProcesaConexion extends Thread{
Socket sc;
FileWriter f;
public ProcesaConexion(Socket sc, FileWriter f){
this.sc=sc;
this.f=f;
}
public void run(){
try{
PrintWriter out=new
PrintWriter(sc.getOutputStream());
BufferedReader bf=new BufferedReader(new
InputStreamReader(sc.getInputStream()));
//recupera los datos enviados por el cliente
//al establecer la conexión
String dato=bf.readLine();
//agrega el resto de datos necesarios
dato=montarCadena(dato);
//escribe la cadena completa en el fichero
//utilizando un bloque sincronizado para evitar
//interferencias entre los clientes
synchronized(f){
f.write(dato);
f.write(System.getProperty ("line.separator"));
f.flush();
f.notify();
}
}
catch(IOException e){
System.out.println("Error en la entrada/salida de
datos");
}
}
public String montarCadena(String dato){
Calendar c=Calendar.getInstance();
//añade la fecha actual a la cadena
String fecha="";
fecha+=c.get(Calendar.DAY_OF_MONTH)+
"-"+(c.get(Calendar.MONTH)+1)+
"-"+c.get(Calendar.YEAR);
dato+=fecha;
//añade el nombre del host a la cadena
dato+="|"+sc.getLocalAddress().getHostName();
return dato;
}
}
AUTOEVALUACIÓN

1. Un objeto URL:

A. Representa la localización de un recurso en una red.

B. Representa la dirección IP de un equipo

C. Contiene la cadena identificativa de un objeto dentro de una determinada


JVM.

D. Representa una conexión abierta con un servidor TCP

2. Si la variable “dir” de tipo String contiene el nombre de un determinado equipo


conectado a una red, para obtener su dirección IP deberíamos utilizar la
instrucción:

A. (new URL(dir)).getIP();

B. (new InetAddres(dir)).getHostAddress();

C. (InetAddress.getByName(dir)).getHostAddress();

D. (new URLConnection(dir)).toString();

3. La excepción UnknownHostException puede producirse:

A. Al crear un objeto Socket

B. Al crear un objeto URL

C. Al crear un objeto URLConnection

D. Al intentar enviar un dato a través de un socket cerrado

4. El siguiente bloque de instrucciones tiene como misión enviar un texto cualquiera


a un servidor a través de un socket. Indica cual es la instrucción que falta en el
lugar indicado:

String textocualquiera=”Texto de prueba”;

String dirserver=”nombre_servidor”;

try{

Socket sc = new Socket(dirserver,1000);

//aquí falta instrucción

out.pintln(textocualquiera);

out.close();

}
}

catch(UnknownHostException e){

System.out.println("host desconocido");

catch(IOException e){

System.out.println("error en la entrada/salida de datos");

A. PrintWriter out = new PrintWriter ();

B. PrintWriter out = new PrintWriter (sc.getOutputStream());

C. PrintWriter out = new PrintWriter (sc);

D. PrintWriter out = new PrintWriter (dirserver);

5. Para establecer una conexión con un recurso de servidor cuya url se encuentra
almacenada en la variable de tipo String “dir”, a través de un objeto
URLConnection, se debería proceder:

A. URLConnection con = new URLConnection (dir);

B. URLConnection con = URLConnection.getInstance(dir);

C. URLConnection con = URL.getConnection(dir);

D. URLConnection con = (new URL(dir)).getConnection();

6. El método accept() de la clase ServerSocket:

A. Puede lanzar una excepción UnknownHostException

B. Bloquea el proceso hasta que se produce una conexión con el servidor

C. Devuelve un objeto ServerSocket

D. Es invocado desde una aplicación cliente para conectar con el servidor

7. Indica cual de las siguientes instrucciones crea de forma correcta un objeto


ServerSocket:

A. ServerSocket servidor = new ServerSocket(“nombre_host”);

B. ServerSocket servidor = Socket.getServer(“nombre_host”);


C. ServerSocket servidor = ServerSocket.getInstance();

D. ServerSocket servidor = new ServerSocket(200);

8. Si a partir de un socket que nos conecta con un host remoto y que está
referenciado por la variable “sc”, queremos conocer la dirección IP de dicho host
deberíamos escribir:

A. sc.getInetAddress().getHostAddress();

B. sc.getRemoteAddress();

C. sc.getHost().getAddress();

D. sc.getLocalAddress();
Ejercicios Propuestos

1. Realizar una programa que solicite por teclado el nombre de un host externo y nos
muestre por pantalla la dirección ip del mismo. Así mismo, se preguntará al
usuario si quiere ver la página de inicio de dicho servidor y, en caso afirmativo, se
solicitará ésta al servidor y se mostrará en la consola (tal cual sea enviada por el
servidor)

Si el servidor no existe se indicará dicha circunstancia en un mensaje.

2. Realizar un programa basado en interfaz gráfica con dos campos de texto donde
el usuario introducirá los nombres de dos servidores (host) remotos. Al pulsar un
botón de título “comprobar”, el programa nos indicará si los servidores se
encuentran o no en el mismo rango de IPs (los tres primeros números de los
cuatro que forman la IP deberán ser iguales).

3. Desarrollar una aplicación de comunicación entre procesos consistente en un


servidor que tiene como misión enviar a la aplicación cliente que establece
conexión con él el contenido de un fichero de texto existente en el servidor (la
localización del fichero estará predefinida en el proceso servidor. El proceso
servidor únicamente podrá atender 10 peticiones clientes simultáneamente.

ƒ En cuanto al proceso cliente, consistirá en una aplicación basada en interfaz


gráfica que incluya un botón “conectar” y un campo de texto multilinea, de
forma que al pulsar el botón se produzca la conexión con el servidor y se
muestre el campo de texto el contenido del fichero de texto enviado por el
proceso.

También podría gustarte