¡Recomienda este blog!

lunes, 11 de abril de 2011

Aplicación Cliente-Servidor: Ahorcado remoto.

Contenido

1. INTRODUCCIÓN.

2. DESCRIPCIÓN DEL SERVICIO A IMPLEMENTAR.

3. DECISIONES DE DISEÑO.

3.1. Tipo de protocolo escogido.
3.2. Presentación e introducción de datos.
3.3. Comunicación cliente – servidor.

4. MANUAL DE USUARIO.

4.1. Compilación de la aplicación.
4.2. Ejecución del cliente y el servidor.

5. BIBLIOGRAFÍA EMPLEADA.

__________________________________________________________

1. INTRODUCCIÓN


En este proyecto se pretende abordar el diseño y la implementación de un programa cliente – servidor. Para concretar, este proyecto se centrará en la implementación del servicio de un Ahorcado Remoto.

El objetivo de este trabajo ya no es sólo la resolución del problema asignado, sino la adquisición de conocimientos por parte de los alumnos acerca del propio modelo cliente – servidor y todo lo que ello conlleva. Entre estos conocimientos merece hacer mención a la apertura y cierre de sockets entre cliente y servidor, así como el establecimiento y cierre de la comunicación y el envío de información entre ellos.

Se entiende este aspecto de la asignatura como un elemento imprescindible ya que los sockets proporcionan un elemento de comunicación entre dos procesos, además de ser elementos versátiles y componentes básicos de comunicación entre interprocesos e intersistemas.

Otro de los fines de este proyecto es prestar atención a la importancia de la capa de transporte dentro de la arquitectura OSI, así como de los protocolos UDP y TCP y la diferencia entre ellos. TCP y UDP son dos protocolos de puertos de comunicaciones que resultan imprescindibles, pero que sin embargo se comportan de manera diferente como se comprobará más adelante.

Como consecuencia de lo dicho anteriormente, este proyecto servirá para asentar a los alumnos los conceptos acerca de los diferentes tipos de clientes y servidores, así como su implementación de forma iterativa o concurrente.

Para poder alcanzar las metas propuestas anteriormente, ha sido necesaria la utilización de una serie de recursos, desde los apuntes proporcionados disponibles en la página de la asignatura, hasta la bibliografía complementaria recomendada por el profesor de la misma, que facilita la comprensión de los conceptos ya citados.

2. DESCRIPCIÓN DEL SERVICIO A IMPLEMENTAR.

El servicio a implementar asignado para este grupo corresponde al servicio de Ahorcado Remoto.

Este servicio consistirá en la implementación del juego del ahorcado mediante su diseño en la estructura Cliente – Servidor.

Para ello el servidor debe tener en su haber una serie de palabras almacenadas en un diccionario disponibles para iniciar el juego, de las cuales elegirá una aleatoriamente para comenzar. Estas palabras formarán parte de una cadena, y en el momento en el que una palabra es seleccionada, esta pasa a formar parte de otra cadena en la que aparecerá con todos sus caracteres ocultos.

Antes de que el servidor pueda enviar la palabra oculta correspondiente, debe esperar a que el cliente realice una petición de conexión al mismo, mostrando así su intención de iniciar una nueva partida del juego.

El cliente dispondrá de un número fijo de fallos, que en este caso será de ocho,tantos como letras tiene la palabra AHORCADO. Cada vez que el cliente cometa un fallo, se añadirá una letra a la palabra AHORCADO, almacenada en otra cadena auxiliar definido para tal fin.

En el transcurso del juego, el cliente irá introduciendo letras en la palabra que se le mostrará como oculta. En caso de que el cliente introduzca una letra que pertenezca a la palabra mostrada, esta será cambiada por su carácter oculto correspondiente. Si la letra introducida no es correcta y no pertenece a la palabra oculta, se mostrará el estado de la palabra oculta tal y como estaba hasta ese momento, es decir, se mostrarán tanto los caracteres ocultos como las letras descubiertas hasta entonces.

Si por alguna razón, el cliente introduce una letra que ya había introducido antes (tanto en caso de acierto como en caso de fallo en la primera vez en la que se introdujo la letra), esta se penalizará y se contará como un error más por parte del cliente, añadiéndose la letra correspondiente de la palabra AHORCADO.

Cabe hacer mención a que el servidor no distingue entre letras mayúsculas y letras minúsculas, y por consecuencia, reciba la letra que reciba, se tomará esta letra como si de una letra mayúscula se tratase.

Por parte del cliente, este no aceptará la introducción por parte del usuario de caracteres que no sean letras del abecedario. Tampoco son aceptadas la letra ‘ñ’ y todas las vocales acentuadas.

En caso de que el cliente acumule ocho fallos, la partida finalizará y el cliente habrá perdido la partida, por lo que se le mostrará un mensaje que se lo indicará. Si por el contrario, el cliente logra adivinar la palabra antes de que se le muestre la palabra AHORCADO, este habrá ganado la partida.

Se enviará por parte del servidor un mensaje que indique el fin de la partida al cliente, tanto si este ha ganado como si ha perdido. El cliente al recibir este mensaje, lo identificará y esperará a recibir otro mensaje más desde el servidor indicándole cuál era la palabra correcta.

Cuando el servidor envíe este mensaje con la palabra correcta, cerrará el socket. De igual manera hará el cliente cuando reciba este mensaje.

3. DECISIONES DE DISEÑO.

3.1. Tipo de protocolo escogido.

En el diseño de este proyecto se ha optado por la selección del protocolo TCP y un servidor con concurrencia real.

Se seleccionó un servicio de transporte orientado a conexión en el que los clientes deben de establecer una conexión con el servidor antes de lanzar sus peticiones. En este servicio se sobrepuso la fiabilidad del servicio, así como la entrega ordenada de los mensajes sobre la mayor simplicidad de un protocolo no orientado a conexión. Por estos motivos la opción por la que se optó fue la de implementar un servidor TCP.

El sistema requiere la necesidad de establecer una conexión entre cliente y servidor antes del comienzo del envío de mensajes entre ambos. Esto es debido a que en caso de no utilizar un servidor de este tipo, si se perdiese una letra enviada por el cliente al servidor, o un mensaje enviado por parte de este último, no se tendría constancia de
ello y por tanto no podría llevarse una cuenta ordenada del número de aciertos y fallos que el cliente se anota.

Por otro lado, pero no por eso menos importante, para la implementación de este servicio, se requiere de un orden en la comunicación, y se acusa la necesidad de que los mensajes no lleguen al destino fuera del orden establecido; puesto que este servicio basa su técnica en la colocación reiterada y ordenada de letras en una palabra desconocida. Si estos mensajes llegasen fuera de orden, o se perdiesen, por un lado el servidor no habría
recibido las letras solicitadas por el cliente, y por otro lado, el cliente no sabría si la letra seleccionada se ha perdido o es que aparecerá en pantalla en otro orden distinto al que este la había enviado.

Se debe hacer mención a la decisión tomada sobre la elección de un servidor concurrente. Se tomó esta decisión debido a la característica principal de este tipo de servidores; un servidor concurrente permite que varios clientes realicen peticiones simultáneas a un mismo servidor. Por tanto se determinó esta opción como la mejor
manera de poder atender a los clientes, y no retardar el servicio hacia los clientes, haciéndoles esperar hasta que el servidor procese todas las peticiones pendientes como ocurre en un servidor iterativo.

Dentro de las diferentes formas entre las que se puede implementar un servidor concurrente, se seleccionó la opción de crear un servidor con concurrencia real, basada en la técnica de creación de procesos hijos mediante en servicio fork (). Este servicio crea un nuevo hijo del proceso activo, y una vez creado deja a este último a cargo de la comunicación con cliente, lo que permite volver a colocar al proceso original a la espera de peticiones de nuevos clientes mediante un bucle infinito.

Por otro lado, en el sistema implementado se puede observar un gran flujo de peticiones y respuestas, lo que favorece aún más la selección de un servidor concurrente, caracterizado por utilizar respuestas que necesitan de múltiples operaciones de entrada – salida.

3.2. Presentación e introducción de datos.

Otro aspecto a tener en cuenta, como ya se mencionó en la introducción, es la transformación de cualquier letra que sea introducida por parte del cliente a una letra mayúscula. Esto es conseguido mediante la utilización de la función toupper que realiza la función ya mencionada del siguiente modo: cada carácter introducido por el cliente se corresponde con un carácter ASCII, por lo que esta función se encarga de restarle al número de carácter correspondiente 32 para asignarle así su homólogo en mayúsculas.

Para una mayor facilidad en el diseño y en la jugabilidad, se ha decidido que sólo se permite la introducción de caracteres que pertenecen al abecedario, excluyendo la letra ‘ñ’ y las vocales acentuadas.

Siguiendo con las decisiones tomadas propias del diseño, se ha querido implementar el cliente de forma que cuando este presione una tecla para enviar una letra al servidor, esta no sólo no aparezca en la terminal del cliente, sino que este no tenga que pulsar la tecla intro. El sistema no realiza esa especie de “eco” y no muestra en su pantalla el mensaje introducido por el cliente, lo que permite hacer el servicio más legible frente a si no se introduce esta mejora.

Todo esto se lleva a cabo gracias a una nueva librería incluida en el sistema. Linux no admite la inclusión de la librería conio.h y como consecuencia, tampoco la función getch(), que es la que permitiría al usuario realizar la operación descrita anteriormente. Por este motivo se ha creado una nueva libería (“miconio.h”), la cual implementa la función elegida que nos permita conseguir el objetivo buscado. Esta librería se importa en el cliente y la función getch() se usa como si se dispusiese de la auténtica librería conio.h.

3.3. Comunicación cliente – servidor.

El servidor permite elegir el puerto por el que se podrán conectar los clientes. Por defecto, este servicio utilizará el puerto 8041, el cual no está asignado según la IANA. Al cliente, por su parte, se le puede indicar el host de destino como parámetro. Si no se indicase nada como parámetro, al ejecutar el cliente se solicitará al usuario el nombre del host o su IP.

Como ya se mencionó en la introducción, el servidor le indicará al cliente (tanto en el caso de haber ganado como de haber perdido la partida) que la partida ha finalizado y cerrará la conexión con este cliente, mientras que sigue escuchando a la espera de recibir más peticiones de otros clientes o de este mismo.

Aparte de recibir la palabra oculta con la que se había jugado la partida, el cliente recibe una cadena que contiene en sus primeros tres caracteres la palabra FIN. El cliente se encargará de comprobar de si en las tres primeras letras de las cadenas que le envía el servidor está la palabra descrita anteriormente. Todo ello se hará mediante una función de comparación, que en caso de que devuelva un uno (las tres primeras letras serán FIN), este sabrá que la partida ha finalizado y procederá a cerrar el socket abierto con el servidor y posteriormente, cerrar la aplicación.

Hay que añadir que se ha decidido fijar el tamaño de los mensajes con el que se comunican cliente y servidor. De esta manera, se simplifica en gran medida la comunicación entre ambos. El tamaño de estos mensajes se ha fijado según el tamaño máximo de las palabras (que en nuestro caso, se ha decidido que sea de 32 caracteres
incluyendo el carácter nulo), añadiéndole 10 caracteres más. En definitiva, el tamaño de los mensajes será de 42 caracteres.

4. MANUAL DE USUARIO.

4.1. Compilación de la aplicación.

Para compilar el programa, se puede utilizar el MAKEFILE (no se adjunta ), utilizando el comando ‘make’ de la siguiente manera:

$ make all

También se puede utilizar el compilador GCC de Linux introduciendo los siguientes comandos según queramos para el cliente o el servidor:

Para el cliente:

gcc Ahorcado_cliente.c socket_utils.c error.c miconio.c -o Ahorcado_cliente

Para el servidor:

gcc Ahorcado_servidor.c socket_utils.c error.c -o Ahorcado_servidor

4.2. Ejecución del cliente y el servidor.

Como ya se ha mencionado varias veces hasta el momento, esta es una aplicación que implementa el servicio del Ahorcado remoto en la arquitectura Cliente – Servidor.

El servidor se arranca en modo superusuario en cualquier terminal del sistema operativo Linux, habiendo compilado este previamente. La razón de que se tenga que ejecutar en modo superusuario es que la ejecución de un servidor requiere del acceso a ciertos privilegios del sistema de los cuales no se dispone en modo usuario.

En otra terminal diferente o incluso en otra terminal de otro ordenador diferente, puede lanzarse la ejecución del cliente. Al igual que el servidor, este debe de ser previamente compilado para poder ser ejecutado, pero a diferencia con él, la ejecución de un cliente no necesita de privilegios para llevarse a cabo.

En el caso en que la ejecución del cliente se lance en un ordenador diferente al que se está ejecutando el servidor, debe indicarse como parámetro en el comando de la ejecución del cliente, la dirección IP propia del ordenador en el que está siendo ejecutado el servidor. O bien, no indicarlo como parámetro, pero será preguntado al usuario al ejecutar el cliente.

Para ejecutar el servidor se escribirá la siguiente línea de comandos (imagen 4.1):

$ sudo ./Ahorcado_servidor

Para ejecutar el cliente podría escribirse la siguiente línea de comandos (imagen 4.2), donde la dirección IP es una elegida para el ejemplo, pudiéndose cambiar según las necesidades del usuario:

$ ./Ahorcado_cliente 192.168.1.5

Una vez establecida la conexión, aparecerán en la terminal del cliente una cadena con una serie de asteriscos, tantos como letras contenga la palabra con la que se haya iniciado la partida.

La misión del cliente es ir introduciendo letras para intentar descubrir el contenido de la palabra oculta. Se mostrará el seguimiento de la palabra en la terminal del cliente, así como los fallos que lleva acumulados.

5. BIBLIOGRAFÍA EMPLEADA.

La bibliografía empleada en la realización de este trabajo ha sido la mostrada a continuación:

- Douglas E. Comer and David L. Estevens, "Internetworking with TCP/IP vol III: client-server programming and applications". Prentice Hall, 1996.

- Behrouz A. Forouzan "TCP/IP Protocol Suite" 4ª Edición, McGraw Hill, 2010.

- Apuntes proporcionados por el profesor de la asignatura Redes II acerca del modelo Cliente – Servidor, la interfaz de sockets y la API en función de los sockets.

- Página web con contenido relacionado con la programación de sockets en c para Linux. http://www.chuidiang.com/clinux/sockets/sockets_simp.php

- Página web donde se encontró el código fuente para poder crear la biblioteca “miconio.h” y poder adaptarla a las necesidades del servicio, así como la utilización de una simulación de la función original getch(). http://www.reloco.com.ar/linux/prog/tecla.html

Autores:
Gabriel Cebrián Márquez.
Estefanía Coronado Calero.
Iván Durango Blanco.

7 comentarios:

Samuel Gutiérrez Jiménez-Peña dijo...

¿Podrías facilitarme el código empleado para la implementación?

Iván Durango Blanco. dijo...

Hola Samuel, el código fuente y todo lo necesario para ejecutarlo lo puedes encontrar aquí:

http://aprendiendo2veces.blogspot.com.es/2011/04/codigo-fuente-cliente-servidor-ahorcado.html

Un saludo y espero que te sirva.

Daniel dijo...

¿Y cuál es la razón para que le hayas omitido los archivos include?
Si vas a publicar un código, es porque quieres que lo usen y que no se malgaste tiempo en chequear el código para agregar lo que falta. Eso es una pendejada. A ti no te debe importar si el que baja el código lo usa tal cual y no aprende nada. Si buscas eso, hazte profesor, no programador.

Iván Durango Blanco. dijo...

Daniel, la razón está en que al publicar la entrada, no se por qué razón el html de Blogger lo entiende como código y lo omite.

De todas formas, pidiéndole un poco de respeto, como ya comenté en el comentario justo anterior al suyo el siguiente enlace (Al final de la entrada):

http://aprendiendo2veces.blogspot.com.es/2011/04/codigo-fuente-cliente-servidor-ahorcado.html

Se encuentra un .rar con TODO el código completo (Makefile incluido) para que solo tengas que compilar y probar.

De todas formas, antes de comenzar a aprender a programar, le ruego, desde el más absoluto cariño, que aprenda a leer y si ya sabe, preste más atención antes de echar por la borda un trabajo y lo que es peor, a una persona.

Gracias por leer mi blog y si puedo ayudarle en algo no dude en preguntar.

Iván Durango Blanco. dijo...

Como extra, decirte que aquellas librerías que no se adjuntan son librerías estándar de C, con lo que no son necesarias ya que deberán venir integradas en tu editor.

Si no están deberás descargarlas de donde corresponda. (Dependerá del Editor que uses)

Invertebrado Diferenciable dijo...

Vale. Me impresiona lo rápido que respondiste, de hecho, me impresiona que lo hayas hecho y eso se agradece.
Te pido las disculpas del caso si fui grosero, pues, pensé que aquello se trataba realmente de un caso más de los que me he topado...En suma, actué sin pensar. Como veo que la realidad es otra, con gusto acepto mi error.
Yo soy de los que programan con el editor de linux, por lo que comprenderás, no hay mucha ayuda del editor, pero está bien así. Cuando estoy buscando ejemplos puntuales, de esos de "copiar y usar", suelo acudir al código, copiarlo y pegarlo y si funciona, lo reviso, lo modifico y lo adapto a mis fines. Si el código es bueno, pero tiene "trabas" (porque no falta) lo considero una pérdida de tiempo. Luego, en un día puntual, como hoy, andando con el mojón atravesado y respondiendo de manera animal, bueno, es muy raro, en verdad, pero te tocó a ti y lamento mucho aquello y dado que te he hecho pasar un mal rato de manera gratuita, estoy en deuda contigo.
Estoy afinando algunas librerías de manejo de string y fechas bastante buenas, y si te sirven, con gusto las comparto contigo para que las publiques en tu blog, si así lo consideras prudente. Como las hice yo, son de dominio público, no me preocupo por eso, porque así como pido, doy.
Gracias por el "raspacachos", a veces, un hombre "racional" necesita uno.
Espero tu respuesta. Mi e-mail debes tenerlo en el interno, por lo que he visto.

Iván Durango Blanco. dijo...

Hola, no te preocupes por que tus disculpas están más que aceptadas. La verdad, me sorprendió mucho tu comentario por que hasta el momento nunca me había pasado algo similar.

Por mi parte, te pido disculpas también por si en algún momento he sido algo brusco, no era mi intención xD.

Te explico, siempre intento responder a todos los mails que recibo, por que considero que es una muy buena forma de aprender (de ahí el título del blog jaja) y por supuesto si existe algo que publique o que haya publicado y contiene algún error, estoy encantado de que alguien me lo diga y entre todos los resolvemos y por supuesto entre todos aprendemos.

Sobre el tema del código, comentarte que nosotros lo desarrollamos en Ansii C, utilizando Ubuntu como distribución de Linux (I love this operating system =) ). Para el desarrollo usamos gedit (en verdad podríamos haber usado eclipse que da menos problemas, pero para sufrir y adquirir bien los conocimientos de la arquitectura cliente-servidor decidimos hacerlo sin editor).

Una vez desarrollado, utilizamos gcc (en el punto 4 de esta entrada puedes ver como lo compilamos de varias formas) con todas las librerías extras para no tener problemas al compilar (usando el makefile anda bien por que lo acabo de probar). Todo esto lo puedes encontrar en los repositorios normales que trae Ubuntu. De todas formas si tienes algún problema, te creo un vídeo o algo para que veas que necesitas, ok?

Te agradezco mucho lo de las librerías, es un muy buen trabajo por que algunas propias de C dejan mucho que desear. Cuando las necesite no dudes que te las pediré!! jaja.

Lo de publicarlas me parece buena idea, pero el trabajo es tuyo y como tal me gustaría que las publicarás en tu blog (por que exponer lo que uno hace es realmente una de las mejores cosas que existen ), y por supuesto me apunto a echarles un vistazo, que seguro que son geniales.

Por último, comentarte que me ha gustado "Sobre Poesías y Otros Ocios" pero es una pena que no le des caña desde 2009...

Un saludo y seguimos en contacto compañero!

Publicar un comentario