Documentos de Académico
Documentos de Profesional
Documentos de Cultura
PRÁCTICA 2
Servidor web multiproceso – Ejemplo
Página 1 -
Laboratorio de Sistemas Operativos Curso 2020/2021
Como se observa, el programa solo saca mensajes informativos si se ejecuta con la opción -g y un valor
mayor que 0. Ejemplo: ./servidorWeb -p 50000 -g 1
Dar al usuario la opción de escoger el nivel de detalle de los mensajes informativos y de depuración con
un parámetro como -g es una buena práctica, porque las necesidades de detalle de un desarrollador y de
un usuario final son muy diferentes. La idea es que, en lugar de usar printf() sin más para mostrar
cualquier mensaje que le parezca interesante al desarrollador, se metan estos mensajes en el cuerpo de
una sentencia if que se ejecutará si el nivel de detalle especificado por el usuario supera un cierto
umbral. Así, el usuario final puede no especificar -g y no se verá abrumado con su pantalla llena de todo
tipo de mensajes que a él no le aportan nada; en cambio, el desarrollador puede poner un valor a -g que
haga que aparezcan los mensajes e incluso jugar con diferentes valores para que ciertos mensajes
aparezcan solo para ciertos valores mínimos de detalle (otra opción típica es que se considere el nivel de
detalle como una máscara de bits y que ciertos mensajes aparezcan solo si están activados ciertos bits en
el nivel de detalle). Como un refinamiento adicional, muchos programas, como el de este ejemplo, sacan
los mensajes de depuración por el canal de error estándar (stderr) y así se pueden separar de los
mensajes de salida estándar del programa.
#include "param.h"
#include "http.h"
/* Crear gestorHTTP */
if ( ( gHttp = http_crear ( param.puerto_escucha ) ) == NULL ){
fprintf( stderr, "\n....ERROR: No se ha podido crear el gestor" );
exit(1);
}
Si vuelve a ejecutar el programa de la misma forma que en el paso anterior, obtendrá algún mensaje
adicional que indica si se ha podido crear el gestorHttp para activar la escucha en el puerto indicado.
Página 2 -
Laboratorio de Sistemas Operativos Curso 2020/2021
#include "param.h"
#include "http.h"
/* Crear gestorHTTP */
if ( (gHttp = http_crear ( param.puerto_escucha ) ) == NULL){
fprintf( stderr, "\n....ERROR: No se ha podido crear el gestor");
exit(1);
}
/* cerrar conexión */
http_cerrar_conexion ( cliente );
break;
case HTTP_SEGUIR_ESPERANDO:
case HTTP_ESPERA_INTERRUMPIDA:
/* En este ejemplo el programa no va a llegar nunca aquí, pero a
medida que avance la práctica, sí será necesario contemplar estos
casos. */
break;
case HTTP_ERROR:
fprintf ( stderr, "\n...ERROR: http_esperar_conexión" );
break;
}
Ejecute el programa con los parámetros del primer paso y observe que esta vez el programa se queda
parado en la función bloqueante http_esperar_conexion(). A continuación, desde un navegador, pruebe a
solicitar el recurso con URL http://IP_DEL_SERVIDOR:50000/index.html. Obviamente el
navegador web no recibirá nada e incluso se quejará de que el servidor ha cerrado la conexión
Página 3 -
Laboratorio de Sistemas Operativos Curso 2020/2021
inesperadamente o algo similar, pues el servidor aún no está programado para enviar recursos, pero al
menos debería ver el mensaje del servidor mostrando que acepta la conexión del cliente y cuál es su IP,
tras lo cual el programa finaliza.
/* leer peticion */
switch ( http_leer_peticion ( cliente, &peticion, 1 ) )
{
case HTTP_OK:
if ( param.nivel_depuracion > 0 )
fprintf ( stderr, "Petición: IP=%s, RECURSO: %s\n",
peticion->ip_cliente, peticion->ruta );
http_destruir_peticion ( peticion );
break;
case HTTP_CLIENTE_DESCONECTADO:
case HTTP_ESPERA_INTERRUMPIDA:
/* En este ejemplo el programa no va a llegar nunca aquí, pero a
medida que avance la práctica, sí será necesario contemplar
estos casos. */
break;
case HTTP_ERROR:
fprintf ( stderr, "\n...ERROR: Error http_leer_peticion \n");
break;
}
}
Ejecute el programa con los parámetros del primer paso, y al igual que en el paso anterior, el programa
se quedará a la escucha. Pruebe de nuevo desde un navegador con el mismo URL del paso anterior. Esta
vez deberá obtener, además de los mensajes de los pasos anteriores, un nuevo mensaje que indica el
recurso solicitado desde el cliente, finalizando seguidamente.
Página 4 -
Laboratorio de Sistemas Operativos Curso 2020/2021
if ( param.nivel_depuracion > 0 )
fprintf ( stderr, "... Recurso solicitado:: %s\n", nombre_fichero );
if ( fd >= 0 ){
http_enviar_respuesta ( cliente, peticion, fd, 1 );
/* http_enviar_respuesta puede que falle (lo indica mediante el valor
que devuelve). ¿Qué hacemos si ha fallado? */
if ( param.nivel_depuracion > 0 )
fprintf ( stderr, " Fichero %s enviado\n", nombre_fichero );
close ( fd );
}
else {
/* No se ha podido abrir el fichero correspondiente al recurso
solicitado, por lo que habría que consultar errno para saber qué ha
pasado y responder con el código HTTP correspondiente (403, 404...) */
http_enviar_codigo ( ... );
if ( param.nivel_depuracion > 0 )
fprintf ( stderr, " No se ha podido enviar el fichero %s\n",
nombre_fichero );
return;
}
}
Si ha situado correctamente la invocación a estas funciones, puede probar el programa añadiendo esta
vez el parámetro que indica donde están los recursos web. Puede probar con esta invocación:
./servidorWeb -p 50000 -g 1 -b /usr/share/doc/ntp
Si usa un navegador con el URL de los pasos anteriores, esta vez sí obtendrá la página index.html, tras lo
cual el programa finalizará, pues este programa de ejemplo sirve un único recurso del servidor.
Partiendo de esta base, podrá desarrollar la primera fase de la práctica con mayor facilidad.
Página 5 -