Para esta práctica nos basaremos en los programas y protocolo que hemos creado en las prácticas anteriores. Vamos a añadir la capacidad de atender a varios clientes simultáneamente hasta un número máximo de conexiones.
Está permitido comentar y debatir la práctica con otros grupos, incluso se recomienda probar el protocolo con otros grupos, pero bajo ningún concepto está permitido compartir o copiar código de otros grupos. Incumplir esta norma acarreará el suspenso de la práctica.
Para implementar conexiones concurrentes se recomienda emplear select o su formato más conveniente poll. no
Cada una de las conexiones que se realicen entre cliente y servidor seguirán el protocolo descrito en la práctica 3 y el protocolo para subir y bajar ficheros descrito en la práctica 4.
Vamos a añadir nuevas peticiones al protocolo: conocer los usuarios conectados, conocer los ficheros, recoger información del servicio y enviar mensajes entre usuarios y subir y bajar ficheros.
Cuando el cliente quiera conocer qué usuarios se encuentran conectados en ese momento al servidor, intercambiarán los siguientes mensajes.
| Cliente | dirección | Servidor |
|---|---|---|
| LISTA | -> | |
| <- | LISTADO | |
| <- | U usuario1 | |
| <- | Y tunombre | |
| <- | U usuario2 | |
| <- | … | |
| <- | E |
Dónde:
Cuando el cliente quiera conocer qué ficheros hay disponibles en el servidor, intercambiarán los siguientes mensajes.
| Cliente | dirección | Servidor |
|---|---|---|
| FICHEROS | -> | |
| <- | LISTADO | |
| <- | fichero1 size1 | |
| <- | fichero2 size2 | |
| <- | fichero3 size3 | |
| <- | … | |
| <- | E |
Dónde:
El cliente puede preguntar al servidor información sobre el tiempo que lleva conectado y el tiempo de vida del servidor.
Para ello se intercambiarán estos mensajes:
| Cliente | dirección | Servidor |
|---|---|---|
| UPTIME | -> | |
| <- | UPTIME t1 t2 |
Dónde:
t1 y t2 pueden ser enteros o flotantes pero deben de ser en segundos.
Cuando el cliente quiera enviar un mensje al chat intercambiara los siguientes mensajes con el servidor
| Cliente | dirección | Servidor |
|---|---|---|
| MSG el_mensaje_que_puede_contener_espacios | -> | |
| <- | MSG nombre el_mensaje_que_puede_contener_espacios |
Dónde:
el mensaje que puede contener espacios: Es el mensaje de texto que deben recibir los demas usuarios. El mensaje sera todo el texto desde MSG hasta el final de la linea, puede contener espacios.
nombre: el nombre del usuario que ha generado el mensaje
El servidor enviara el mensaje de respuesta a ese cliente y a todos los demas clientes que esten conectados y correctamente autenticados. En la respuesta el servidor incluira el nombre del usuario que envia el mensaje para que los demas vean de quien viene
Eso significa que en cualquier momento cuando el cliente esta esperando otros mensajes puede llegarle un mensaje de tipo MSG. En ese caso el cliente debera procesar el MSG y seguir esperando la respuesta que esperaba.
La forma más simple para que el cliente reciba los mensajes es que envíe periódicamente peticiones de UPTIME para forzar a que se impriman los mensajes pendientes.
Implementar un servidor que acepta clientes simultáneos y soporte los dos nuevos mensajes: conocer los usuarios conectados y recoger información del tiempo.
Implementar un cliente que soporte los nuevos mensajes. El cliente es practicamente el mismo. A partir del desarrollo de la práctica anterior, en el mismo menú en el que hemos dado al usuario la opción de cambiar y conocer su nombre, vamos a añadir qué usuarios hay conectados y el tiempo que lleva el servidor funcionando y nosotros conectados. Recuerda que el proceso de registro y autentificación es automático (el usuario no interacciona con la aplicación), mientras que para estas opciones, sí que mostraremos opciones para que elija.
Si bien la forma de llamar al cliente no cambia, la del servidor sí ligeramente:
FORMATO
servidor <puerto> <número_máximo_de_conexiones> <userfile> <directoriodeficheros> <numero_retos_login>
DESCRIPCIÓN
<puerto> puerto en el que escuchar, por ejemplo 6000
<número_máximo_de_conexiones> número máximo de clientes que podrán conectarse al servidor
<userfile> nombre de fichero con los usuarios con el mismo formato que en la practica 3, si no se incluye se utilizara server_users
<directoriodeficheros> nombre de un directorio en el que se subiran los ficheros que envien los usuarios
<numero_retos_login> número máximo de retos a pedir en el login si no se incluye utilizará 3 retos
Si se alcanza ese número máximo de conexiones, el servidor denegará la conexión y la cerrará directamente.
El servidor mostrará por pantalla información relevante del proceso, aunque el objetivo es que cumpla con el protocolo. Seguidamente se muestra un ejemplo de cómo podría ser la ejecución del servidor:
$ ./servidor1 6000 2 users files 10
Escuchando conexiones en el puerto 6000
Conexión establecida desde la IP 10.1.1.123 puerto 32125
Usuario abc123 autentificado
1 usuario conectado
Usuario ddd222 autentificado
2 usuarios conectados
Nueva conexión denegada, número máximo de clientes alcanzado
Usuario abc123 ha cerrado la conexión
1 usuario conectado
Enviando información de usuarios a ddd222
Enviando información de tiempo a ddd222
Usuario ddd222 ha cerrado la conexión
No hay usuarios conectados
Realizar un cliente que cumpla el protocolo.
Esta es la especificación del cliente:
FORMATO
cliente <ip> <puerto> <userid> [<secreto>]
DESCRIPCIÓN
<ip> IP en formato IPv4, por ejemplo, 10.1.1.101
<puerto> puerto al que conectarse, por ejemplo 6000
<userid> userid para emplear en la autenticación
<secreto> secreto para la autenticación
El userid debe proporcionarse en la llamada a cliente y puede proporcionarse tambien el secreto. Si se proporcionan los dos el cliente utilizara ese <userid> y <secreto> para autentificarse.
Si el secreto no se proporciona se le preguntara al usuario.
Bajo ningun concepto el cliente cargará el secreto de un fichero y especialmente es un error que el cliente abra y cargue datos del fichero usuarios del servidor.
El cliente se autenticará con el usuario indicado y permitirá realizar las funciones del chat: enviar y recibir mensajes a los demas y subir y bajar ficheros
Seguidamente se muestra un ejemplo de ejecución. El interfaz no es importante, puedes elegir la forma que prefieras, pero debe funcionar con el protocolo dado.
$ ./cliente 10.1.1.101 6000 mikel rcPASS4M1k3l
Autenticando con usario mikel
reto 1 respondido
reto 2 respondido
reto 3 respondido
Autenticado OK
1- consultar nombre
2- cambiar nombre
3- ver usuarios
4- ver ficheros
5- subir fichero
6- bajar fichero
7- enviar mensaje
8- ver tiempo y mensajes recibidos
9- cerrar conexion
El cliente debe soportar al menos un interfaz minimo como ese. Pero se valorara mejorar el interfaz. Un interfaz mejor será que no haya que enviar una peticion UPTIME para ver los mensajes sino que aparezcan en cuanto lleguen. Por ejemplo algo asi
$ ./cliente 10.1.1.101 6000 mikel rcPASS4M1k3l
Autenticando con usario mikel
reto 1 respondido
reto 2 respondido
reto 3 respondido
Autenticado OK
Lo que escriba se enviara como mensaje al chat.
Si quiere ver los usuarios escriba \users
Si quiere ver los ficheros escriba \files
Si quiere cambiar el nombre escriba \name
Si quiere subir un fichero escriba \put fichero
Si quiere bajar un fichero escriba \get fichero
\users
Usuarios conectados: alice, bob, *mikel
Hola
mikel: Hola
alice: hola gentes
\put poster.png
He subido el poster
mikel: He subido el poster
bob: dejame ver
bob: yo he subido un nueva lista de tareas
\files
En el servidor hay estos ficheros
- poster.png
- tareas.txt
\get tareas.txt
Bajando tareas.txt
En el mismo directorio para prácticas que creamos en la práctica anterior, se creará un directorio que se llame practica5. En practica5 existirán al menos estos ficheros:
El fichero Makefile tendrá al menos cuatro objetivos: all, cliente, servidor y clean:
El objetivo all compilará tanto cliente como servidor
El objetivo clean será capaz de borrar los ejecutables cliente y servidor. Muy importante: no borrar las fuentes cliente.c, cliente.c
Los ficheros que se entregan se recogerán directamente de Bitbucket y no se aceptarán otros métodos.