/NanoChat

A simple chat app in Java. It uses our designed and implemented UDP and TCP protocols. Juts the back-end with some simple commands.

Primary LanguageJavaMIT LicenseMIT

NanoChat

Aplicación Java cuya funcionalidad es la conexión de clientes a un servidor de chat, haciendo uso de un intermediario que es un directorio o servidor con las listas de chats que gestionará las peticiones de los clientes. La aplicación gestiona los protocolos UDP y TCP para las comunicaciones entre clientes, servidores y el directorio. Proyecto final de la asignatura de Redes de Comunicaciones del segundo año del grado de Ingeniería Informática en la Universidad de Murcia.

Funcionamiento de la aplicación

Las diferentes comunicaciones se llevan a cabo a través de algunas funciones, algunas de las más importantes son:

Función Acción
getServerForProtocol() Es usada por los clientes, le envían un mensaje de petición de información sobre cierto servidor de chat al Directory, y este último deberá de buscar en su lista de servidores de chat el que el cliente ha pedido(usando el protocol que se pasa como argumento), en el caso de que ese servidor exista pues le mandarán la información necesaria(sendServerInfo), y este obtendrá su IP mediante la función getAddressFromResponse().
registerServerForProtocol() Es usada por los servidores de chat y como su nombre indica, dado un protocolo intentarán registrar el servidor de chat en el server Directory, que se registrará satisfactoriamente(sendOK) a no ser que este ya esté registrado.
processRequestFromClient() Es la función que usa el Directory para ir analizando y tratando los distintos tipos de mensaje y peticiones que le envían tanto clientes como servidores de chat.

A continuación se hace un breve resumen de cómo funcionan el directorio, el servidor de chat y el cliente de chat con sus respectivos autómatas de funcionamiento.

Funcionamiento del servidor de directorio

El servidor del directorio se inicializa y queda esperando a la llegada de una solicitud de un servidor o de un cliente. Este estado inicial recibe el nombre de qWAIT, y además es el único estado final del autómata. Una vez que se encuentra en este estado, puede pasar a dos estados diferentes: cuando se recibe una petición de un cliente de chat de obtener información de un servidor (rcv(getServer), se pasa al estado q3. Entonces se revisa el conjunto de los servidores almacenados, y se vuelve al estado qWAIT con la información(send(info)) o con un mensaje en el que se especifica que el servidor no se encuentra registrado en el directorio (send(empty)).

Por otro lado, cuando en el estado qWAIT se recibe una solicitud de un servidor de chat para ser registrado (rcv(registerServer)) se pasa al estado q2. En este estado se intenta registrar el servidor. Si ya existe, se retorna al estado qWAIT con la denegación del registro (send(denied)). Sin embargo, cuando esto no sucede el servidor se registra y se devuelve la confirmación de esto (send(confirmed)).

Autómata del directorio

Autómata del directorio

Funcionamiento del cliente de chat

El cliente de chat tiene un estado inicial q1. Este estado además es final. Cuando el cliente decide enviar una solicitud al directorio para obtener la dirección de un servidor (send(query)), el autómata pasa al estado q2. En este estado pueden suceder diferentes cosas: si obtenemos una respuesta del directorio, volveríamos al estado inicial con la información del servidor (rcv(info)) o, en caso de no estar registrado en el directorio, con un mensaje que indica que el servidor de chat no está registrado (rcv(empty)).

Sin embargo, si se excede un tiempo máximo preestablecido (el timeout), el autómata pasa a un siguiente estado q3 idéntico en el que se vuelve a solicitar al directorio la información. El autómata está simplificado, pero este proceso se repetiría 10 veces en caso de error, y si el décimo también excede el timeout, el autómata llega al estado qerr, estado “trampa” al que se llega tras exceder todos los timeouts del que no se puede salir y es final.

Autómata del cliente

Autómata del cliente

Funcionamiento del servidor de chat

El servidor de chat tiene un estado inicial q1 que además también es su único estado final. En este estado inicial se pueden mandar solicitudes al directorio para ser registrados en él (snd(registration)), pasando de esta manera al esta q2 del autómata. En este estado del autómata se puede retornar al estado inicial con la confirmación del registro (rcv(confirmed)) o, en caso de hallarse ya en el directorio, el mensaje de denegación del registro (rcv(denied)).

Sin embargo, si se excede el timeout preestablecido, se pasará a un estado q3 en el que se volverá a enviar la solicitud de registro al directorio retornando de esta manera a q2.

Autómata del servidor

Autómata del servidor

Formato de los mensajes

Se han utilizado diversos formatos de mensajes durante la elaboración del nano-chat. Estos formatos se han elaborado para funcionar sobre los dos protocolos de nivel de transporte que había que utilizar: UDP para los mensajes encargados de comunicar el directorio con los clientes y servidores del chat, y TCP para el mecanismo de comunicación entre el cliente y el servidor de chat.

Mensajes de UDP

A continuación se presentan y explican brevemente los mensajes creados para la comunicación entre el directorio en la clase DirectoryThread y el cliente o servidor de chat con la clase DirectoryConnector.

  • Mensaje de consulta del cliente: Tiene el código de operación opcode = 0. Es el mensaje usado por el cliente de chat para consultar al directorio la dirección de un servidor asociada a cierto protocolo (getServerForProtocol). Ocupa 5 bytes, 1 para el opcode y 4 para el protocolo (que es un entero).
  • Mensaje de registro del servidor: Tiene el código de operación opcode = 1. Es el mensaje usado por el servidor de chat para solicitar su registro en el HashMap que almacena en el directorio los diferentes servidores asociados a los protocolos (registerServerForProtocol). Ocupa 9 bytes, uno para el opcode, 4 para el protocolo y 4 para el puerto del servidor.
  • Mensaje de confirmación/denegación del servidor: Tiene el código de operación 2. Este mensaje es la respuesta del directorio a la solicitud de registro del servidor (sendOK), y ocupa 2 bytes, uno para el opcode y otro para un byte b que está programado para poder tener dos estados posibles. El valor b puede tomar el valor 1 en el que se confirma la solicitud cuando el protocolo del servidor no tiene asociado ningún servidor en el directorio y de esta manera se confirma el registro; o puede tomar el valor 0 cuando ya existe un servidor asociado al protocolo denegando de esta manera el registro.
  • Mensaje de información del servidor: Tiene el opcode = 3. Es el mensaje que responde el directorio a una solicitud del cliente getServerForProtocol() cuando existe el servidor en el directorio (sendServerInfo). Ocupa 9 bytes, 1 para el opcode, 4 para la dirección IP en formato de array de bytes y 4 para el puerto del servidor (entero).
  • Mensaje de no existencia del servidor: Tiene el código de operación 4. Este mensaje complementa al anterior, ya que es el mensaje que se manda cuando para la solicitud mencionada del cliente no hay servidor registrado (sendEmpty). Consta de un solo byte, el del opcode.

Mensajes una vez conectado al servidor de chat

A continuación se presentan los diferentes formatos de mensajes utilizados para la comunicación entre cliente y servidor, referente a las tareas del boletín 6. Se ha utilizado lenguaje de marcas. Posteriormente se encuentran los mensajes de respuesta.

Mensajes del cliente

Mensaje Opcode Comando Tipo de mensaje
Registrarte en el servidor con un nick 3 “nick nombre”(COM_NICK) NCRoomMessage
Intentar entrar a una sala 2 “enter nombre”(COM_ENTER) NCRoomMessage
Pedir una lista de las salas existentes en el servidor 1 “roomlist”(COM_ROOMLIST) NCRoomMessage
Enviar un mensaje de chat al servidor 4 “send mensaje”(COM_SEND) NCRoomMessage
Salir de una sala del servidor de chat 5 “exit”(COM_EXIT) NCOpcodeMessage
Pedir información acerca de la sala en la que te encuentras 7 “roominfo”(COM_ROOMINFO) NCOpcodeMessage
Salir del servidor de chat 8 “quit”(COM_QUIT)
Pedir ayuda acerca de los comandos disponibles 9 “help”(COM_HELP) NCPmMessage
Enviar un mensaje privado a un usuario de tu sala 10 “sendpm user mensaje”(COM_SENDPM) NCRoomMessage
Cambiar el nombre de la sala 11 ”changeroomname nombre”(COM_CHANGEROOMNAME) NCRoomMessage
Esperar una supuesta recepción de mensaje en la sala 12 " "(COM_SOCKET_IN)

Mensajes de respuesta

Mensaje Opcode Código de opcode Tipo de mensaje
El nick ha sido aceptado 2 OP_NICK_OK NCOpcodeMessage
El nick ha sido rechazado 2 OP_NICK_DUPLICATED NCOpcodeMessage
El cliente ha sido aceptado en la sala 21 OP_ACCEPTED NCOpcodeMessage
El cliente no ha sido aceptado en la sala 22 OP_DENIED NCOpcodeMessage
El cliente “x” ha salido de la sala 25 OP_USERLEFT NCRoomMessage
El cliente “x” ha entrado en la sala 26 OP_USERENTERED NCRoomMessage
Se ha cambiado el nombre de la sala 27 OP_NAMECHANGED NCRoomMessage
La lista de mensajes que tiene guardados la sala 28 OP_NAMENOTCHANGED NCRoomMessage
La lista de la información de las salas 51 OP_INFOLISTED NCListMessage
El mensaje que envía un usuario por la sala 61 OP_RCVMESSAGE NCRoomMessage
El mensaje privado ha sido enviado satisfactoriamente 63 OP_SENT NCRoomMessage
El mensaje privado no se ha podido enviar 64 OP_NOTSENT NCRoomMessage
La lista de mensajes que tiene guardados la sala 66 OP_HISTORYPRINTED NCStringListMessage