# AI16 : Projet de chat en Java
<!--
Rapport : uniquement les fichiers PDF sont acceptés. Dans le rapport, il faut avoir :
- Une partie contexte dans laquelle vous expliquer le projet, les concepts, les objectifs fixés et les cas d’utilisation théorique (schémas)
- Une partie qui explique et justifie votre conception et le développement (ex. Le choix des structures des données JAVA, surcharges des méthodes). Vous pouvez vous appuyer sur des bouts de code et des schémas.
- Une partie scénarios qui explique comment récupérer (ex. code sur git avec un commit), installer et lancer votre application. De plus, vous devez montrer tous les cas d’utilisations pratiques (via votre application sous forme d’un démonstrateur)
-->
## Introduction
Ce projet a pour but d'implémenter une application console rudimentaire de chat. Les fonctionnalités sont les suivantes :
- Pouvoir s'identifier par un pseudo unique sur le serveur
- Visualiser la connexion d'un nouvel utilisateur
- Pouvoir écrire un message sous un pseudo qui sera envoyé à tous les autres utilisateurs connectés
- Visualiser la déconnexion d'un utilisateur
Du côté technique, le tout sera géré par un serveur qui sera chef d'orchestre des connexions et des messages échangés :
- Il devra créer et gérer les threads associés aux sockets de chaque nouvelle connexion
- Quant à eux, les threads devront gérer les entrées et sorties d'information en fonction des données décodées du protocole
Du côté du programme client, il proposera de :
- Pouvoir se connecter au serveur principal de chat
- Définir un pseudonyme avec lequel l'utilisateur sera identifié dans ses messages
- Envoyer des messages (en son nom/pseudonyme)
- Recevoir des messages et les afficher de manière lisible
- Quitter la conversation à l'aide d'une simple commande
- Être averti de la connexion ou de la déconnexion d'un utilisateur
## Contexte <!-- Partie du prof -->
Ayant des niveaux disparates en conception orientée objet et en Java, nous avons beaucoup travaillé conjointement, en "pair programming" !
Ainsi, nous avons tous pu comprendre la logique algorithmique, la logique orientée objet et l'architecture du projet.
C'est également pourquoi, les différents auteurs des commits ne sont pas forcément représentatifs de la participation de chacun.
## Scénarios
### Installation
Pour une meilleure expérience lors de l'utilisation du client, nous conseillons d'utiliser le logiciel sous un système UNIX (Linux, MacOS) ou WSL.
Cloner le repository git
```bash
git clone https://gitlab.utc.fr/ppompean/ai16p21
cd ai16p21
```
Compiler tous les fichiers java dans le dossier `out`
```bash
javac -d out src/*/*.java
```
### Démonstration
Voici une démonstration de notre application en cours d'utilisation.
Le serveur est d’abord lancé à gauche.
Puis deux clients sont lancés à droite.
Ils se connectent, entrent leur nom, et échangent quelques messages.
Puis celui du dessus s’en va en killant le client (Ctrl-C).
L’autre se déconnecte avec la commande /quit
[](https://asciinema.org/a/404914)
*En cas de souci pour accéder à la vidéo, voici le lien : https://asciinema.org/a/404914*
Nous n'avons pas tout montré dans ce stream, ajoutons quelques points sur l'implémentation de l'application :
- Les erreurs devraient être traitées correctement.
- Un client n'a pas accès à la conversation tant qu'il n'a pas donné son pseudo.
- Un client peut changer de pseudo en cours de route.
- En cas d'échec de la connexion au serveur, le client quitte immédiatement.
- Si le serveur détecte que le client ne respecte pas le protocole défini, il refuse la connexion.
- Le serveur écoute sur le port 10800
- Les clients se connectent à localhost, nous n'avons pas implémenté de lecture d'argument en ligne de commande pour des raisons de simplicité. Pour se connecter à un serveur distant, éditer le code source de `src/client/MainClient.java`.
### Première utilisation
#### Serveur
Lancer le serveur dans un premier terminal :
```bash
cd out
java server.MainServer
```
Le serveur log toutes les requêtes entrantes.
Aucune action n'est prévue côté serveur.
#### Client
Lancer dans $n$ terminaux des clients :
```bash
cd out
java client.MainClient
```
Avant de pouvoir rejoindre la conversation, il faut donner son nom avec la commande `/nick <nickname>`.
Une fois le nom accepté, on peut commencer à discuter en tapant ses messages puis en appuyant sur entrée.
Les messages reçus du serveur sont en jaune ou en rouge (pour les erreurs), afin d'être plus facilement différenciés des messages entrés par l'utilisateur ou l'utilisatrice.
## Conception

*https://i.imgur.com/OkDwzs0.png*
Nous avons choisi ici de représenter les dépendances (lignes directionnelles pointié) entre les classes. Il s'agit par exemple d'un appel de méthode static depuis la classe, d'un type de variable ou de paramètre utilisé, ou bien encore d'une instanciation d'objet. Pour plus de lisibilité, les dépendances bidirectionnelles ont été représentées par des associations (lignes pleines).
### Paquet *server*
Le paquet *server* réuni les composants nécessaires au démarrage du programme serveur de l'application. Le paquet seul n'est pas suffisant, puisque le serveur nécessite aussi le paquet *exception* et le paquet *protocol*.
### Paquet *client*
Le paquet *client* est similaire au paquet server, dans le sens où il permet de démarrer le programme en version client avec le paquet *protocol* en plus.
Pour résumer, le serveur n'a pas besoin du paquet client pour fonctionner et inversement.
### Paquet *protocol*
Le paquet *protocol* réuni toutes les classes liées à l'implémentation du protocole (que nous détaillerons dans la partie suivant). Ainsi, on retrouve le cœur du paquet, qui est la classe *Protocol* et qui contient toute la logique du protocole. On retrouve aussi la classe *Packet* qui encapsule les données envoyées et reçues par le protocole et qui fournit toutes les méthodes nécessaires associées. Enfin, on retrouve l'*enum* *ProtocolType* que nous allons décrire par la suite.
Les classes de ce paquet sont utilisées et par le serveur et par le client. Il s'agit en quelque sorte du "contrat" signé entre les deux parties pour s'accorder sur la méthode de communication.
### Paquet *exceptions*
Le paquet *exceptions* ne contient qu'une seule classe héritant du type *"Throwable"*. Elle est utilisée par notre programme lorsque le protocole de connexion n'a pas été validé entre les deux parties.
### Protocole
Au début, nous avions eu l'idée d'implémenter un protocole pour nos communications client <=> serveur.
De cette manière les informations ne se mélangent pas entre différents messages et leurs frontières et types sont clairement définies.
Nous avions prévu le format suivant : `<byte><short><utf8>`
A savoir :
- Un `<byte>` pour donner le type de message
- Un `<short>` pour donner la longueur du message
- Et pour finir un chaîne `<utf8>` pour le message
Il existe quatre types de base dans l'enum `ProtocolType` ayant chacun une signification :
- MESSAGE : stipule que l'information envoyée correspond à un message
- NICK : signifie que le message qui va suivre est un nom d'utilisateur
- QUIT : ce message est un message de déconnexion, l'utilisateur à quitter la conversation
- ERROR : ce message retranscrit une erreur
Cependant, après quelques recherches, nous nous sommes rendu compte que quelque chose de similaire existait déjà dans les méthodes de la class`DataOutputStream`.
Nous avons donc utilisé les méthodes :
- `.writeByte`
- `.writeUTF`
Elles permettent respectivement d'envoyer un `<byte>` correspondant au type de message et une chaîne `<utf8>` sans se soucier de sa longueur.
Par extension, notre code se veut très évolutif car le `<byte>` représente 256 valeurs et nous n'en exploitons que 4. On pourrait par exemple imaginer faire évoluer le code en ajoutant le type `WHO` ou bien le type `VOTE`. Qui permettrait respectivement d'afficher la liste des membres connectés ou de créer un sondage par exemple. De plus, cette façon de transmettre les informations est très légère en données et donc plutôt écologique.
## Conclusion
Ce projet rassemblant des participants de niveaux très disparates, nous avons dû le réaliser en bonne partie ensemble, c'est pourquoi les contributions ne sont pas toujours pertinentes. Pour Clément, il a énormément appris en JAVA et en POO grâce à ce projet car il ne lui avait jamais été donné de les côtoyer auparavant. Thomas et Paco, côtoyant les concepts dans leurs entreprises, ont pu tout t'expliquer au fur et à mesure de ce qu'ils faisaient. Bonnes pratiques et concepts ont pu être inculquées, revues et appliquées par chacun d'entre nous dans l'accomplissement du projet. Chacun ayant une vision d'ensemble du projet.
Le diagramme de classe nous a permis de nous rendre compte que notre code était encore améliorable, notamment sur la réduction des dépendances. Nous en restons satisfait, puisqu'il est - de notre point de vue - grandement modulable. Au vu de la souplesse de modularité de notre programme, il est probable que nous améliorerons le chat par la suite.
Vous pouvez aussi vous connecter pour les tests en remplaçant `"localhost"` dans `src/client/MainClient.java` par `"ppom.me"`.
Vous trouverez ci-dessous le lien vers notre Gitlab UTC.
[](https://gitlab.utc.fr/ppompean/ai16p21)
*https://gitlab.utc.fr/ppompean/ai16p21*