PDF de programación - Práctica 5: Servidor web concurrente en Java

Imágen de pdf Práctica 5: Servidor web concurrente en Java

Práctica 5: Servidor web concurrente en Javagráfica de visualizaciones

Publicado el 5 de Abril del 2020
58 visualizaciones desde el 5 de Abril del 2020
61,3 KB
12 paginas
Creado hace 10a (26/11/2009)
Práctica 5: Servidor web concurrente

en Java



Esta práctica pretende familiarizar al alumno con la programación de
servidores que emplean sockets TCP. Para ello partiremos del servidor web
básico visto como ejemplo en las clases de teoría (incluido como anexo al
final del capítulo), y lo modificaremos para obtener un servidor web
concurrente, capaz de admitir conexiones simultáneamente con varios
clientes.

Nuestro servidor seguirá la versión 1.0 del protocolo HTTP definida
en el RFC 1945 (http://www.ietf.org/rfc/rfc1945.txt), aunque
no permitirá todas sus posibilidades de intercambio de información, sino
sólo un subconjunto reducido de las mismas. Como ya hemos estudiado,
esta versión emplea conexiones no persistentes, es decir, el cliente realiza
una conexión TCP distinta para cada uno de los objetos que componen la
página web. Por lo tanto, cada petición se tratará de forma independiente y
no es necesario mantener información de estado de una petición a la
siguiente, lo que simplifica la implementación del servidor. Por otra parte,
nuestro servidor debe ser capaz de atender varias peticiones concurren-
temente, por lo que debe ser multihilo. Esto nos permitirá estudiar un
ejemplo sencillo de servidor concurrente y ver las diferencias en la
estructura con respecto al caso iterativo.

P5-2

Prácticas de Redes de Computadores
En los siguientes apartados abordaremos diferentes aspectos que

deben resolverse para la correcta implementación del servidor propuesto.

1. Clases para comunicaciones

Como sabemos el servicio de web utiliza para transferir sus mensajes
el protocolo de nivel de transporte TCP. Por ello, en este apartado veremos
las clases básicas para comunicar un cliente y un servidor mediante sockets
TCP. La información que proporcionamos sobre las clases java que hay que
emplear y sus métodos es bastante limitada. Para ver los detalles es
aconsejable consultar la página web de Sun con información sobre java
(http://java.sun.com/javase/6/docs/api). También puede ser de
interés consultar el documento:

http://www.ulpgc.es/otros/tutoriales/java.
Como mínimo necesitaremos dos clases pertenecientes al paquete

java.net.*, las clases Socket y ServerSocket.
Socket permite establecer una conexión entre un cliente y un
1.
servidor TCP. El cliente crea un socket e inicia la conexión con el
servidor. Una vez conectado al otro extremo utiliza este socket para el
envío y la recepción de información.
ServerSocket permite a un servidor escuchar en un puerto a la
2.
espera de una conexión TCP. Al establecerse ésta, en el programa
servidor se crea un objeto de la clase Socket que se emplea para el inter-
cambio de información posterior entre ambos extremos.

Nuestro servidor esperará las conexiones de los clientes escuchando
en un puerto previamente determinado. Como nuestro proceso no tiene
privilegios de administrador, el puerto con el que trabaje el servidor deberá
ser uno mayor que el 1023. Por ejemplo, podemos elegir el 8000.

Para esperar la conexiones hay que invocar el método accept() de
la clase ServerSocket. Este método bloquea la ejecución del programa a
la espera de una conexión. Al recibir una petición, accept() crea un nuevo
objeto de la clase Socket, que se usará durante el resto de la comunicación
con el cliente.

El empleo del método accept() puede generar una excepción
IOException, por lo que, o bien habrá que capturarla mediante una cláu-
sula try, tal y como se hizo en la práctica anterior, o bien puede lanzarse
(throws) al programa o función que llamó al método que genera la

Servidor web concurrente en Java
P5-3
excepción. De esta manera no será necesario programar una cláusula try.
En nuestro caso, dado que es la máquina virtual Java quien llamó al método
main, esta excepción se lanzará hacia ella.

2. Gestión de la entrada/salida

Una vez conectado con un cliente, con el fin de comprobar y depurar
el funcionamiento del servidor, éste VISUALIZARÁ POR PANTALLA
LAS CADENAS DE CARACTERES que reciba del cliente. Para manejar
la transferencia de información a través del socket, la clase Socket dispone
de dos métodos: getInputStream() y getOutputStream(), que pro-
porcionan un flujo de entrada y uno de salida, respectivamente. Como ya
vimos en una práctica anterior, es mejor no manejar estos flujos
directamente, sino anidados a través de otras clases como Scanner y
PrintWriter y, al igual que hicimos allí, serán las que empleemos.

A continuación se muestra, de forma breve, un ejemplo de uso de

estas clases y algunos de sus métodos:

Scanner recibe = new Scanner (cliente.getInputStream());
System.out.println(recibe.nextLine());
PrintWriter envia = new
PrintWriter(cliente.getOutputStream());
envia.println(“GET / HTTP/1.0”);

donde cliente es un objeto de la clase Socket conectado con un cliente.


3. Descripción del protocolo e implementación del servidor

El servidor que vamos a realizar sigue la versión 1.0 del protocolo
HTTP. No obstante, nuestro servidor no implementará todo el protocolo,
sino únicamente un subconjunto de éste. En este apartado vamos a explicar
qué parte implementaremos. Para ello necesitamos conocer, qué peticiones
debe ser capaz de servir y cómo responderá a esas peticiones.

HTTP emplea dos tipos de mensajes: peticiones de los clientes a los
servidores y respuestas de los servidores a los clientes. Ambos poseen una
estructura similar formada por tres campos: una línea inicial que se incluye
siempre, a continuación puede haber una o más cabeceras (en la versión 1.0
ninguna es obligatoria), y por último, un cuerpo que no siempre estará
presente. Tras finalizar las cabeceras (o después de la línea inicial, en el



P5-4
Prácticas de Redes de Computadores
caso de que no haya ninguna cabecera) debe haber una línea en blanco,
formada por los caracteres ASCII: CR y LF (retorno de carro y salto de
línea, respectivamente).

Mensaje de petición del cliente
En los mensajes de petición la línea inicial contiene la orden deseada
por el cliente. Aunque el estándar especifica varias órdenes posibles, la más
habitual es la orden GET, que será la única que implementaremos. Esta
orden permite al cliente solicitar objetos almacenados en el servidor.
Comienza con la palabra reservada GET, le sigue el objeto solicitado por el
cliente y finaliza con la versión del protocolo empleado. En el caso de la
versión 1.0 tiene la forma:

GET objeto HTTP/1.0 CR LF CR LF

Donde, como se ha indicado, CR LF son los caracteres de retorno de carro y
salto de línea, respectivamente. Por ejemplo, para poder obtener la página
web
un
navegador se conectará al puerto 80 del servidor www.upv.es y enviará la
orden:

a http://www.upv.es/index.html,

correspondiente

← línea en blanco enviada también por el

GET /index.html HTTP/1.0

navegador.

Nuestro servidor sólo analizará la línea inicial de los mensajes de
petición y no se preocupará del resto. Para interpretar la línea de petición, el
servidor necesita analizar cada una de las palabras que la componen. Esta
tarea podemos resolverla fácilmente mediante la clase java Scanner que
nos permite leer el siguiente elemento (String) de un flujo de entrada,
mediante el método next(). Como ya hemos mencionado, la descripción
de dicha clase se puede consultar en la página web de Sun.

Como nosotros sólo vamos a implementar la orden GET, nuestro
servidor sólo tiene que comprobar si la primera palabra de la cadena es
“GET”, y en caso afirmativo identificar qué fichero ha solicitado el cliente.
Para comprobar que la petición es un GET podemos emplear cualquiera de
los métodos que tiene la clase String para comparar dos objetos de ese
tipo, como equals, equalsIgnoreCase o startsWith. Si el servidor
tiene el fichero solicitado (y el cliente dispone de los permisos necesarios
para acceder a él), el servidor debe enviárselo al cliente, y en caso contrario
responder con un mensaje de error.

Servidor web concurrente en Java

P5-5

Mensaje de respuesta del servidor
La respuesta a una petición GET incluye los tres campos que hemos
mencionado antes, y es necesario que nuestro servidor los emplee todos.
Veamos que información debemos poner en cada uno de ellos:

Campo 1: la línea inicial

En el caso de la respuesta de un servidor esta línea se denomina línea

de estado y emplea el formato siguiente:

versión num cadena

donde versión es la versión del protocolo utilizada, num es un código
numérico de tres cifras que expresa el resultado de la petición realizada por
el cliente, y por último, cadena es una cadena de caracteres que también
indica el resultado de la operación pero ahora en un formato fácilmente
comprensible por los programadores. Algunos de los valores de los últimos
dos campos son:



Num
200
304
400
401
404
501

Cadena

OK
Not Modified
Bad Request
Unauthorized
Not Found
Not Implemented

La línea de estado típica de la versión 1.0 para indicar que se envía el objeto
pedido por el cliente es:

HTTP/1.0 200 OK

Si, por el contrario, el servidor no dispone del objeto solicitado responderá
con:

HTTP/1.0 404 Not Found

Estas son las dos líneas de estado que nuestro servidor debe implementar.

Campo 2: las líneas de cabecera

Aunque la versión 1.0 no establece ninguna cabecera obligatoria lo
habitual es que los servidores envíen varias líneas de cabecera en sus
respuestas. Estas
  • Links de descarga
http://lwp-l.com/pdf17494

Comentarios de: Práctica 5: Servidor web concurrente en Java (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios
Es necesario revisar y aceptar las políticas de privacidad