Cours 6 : Programmation Réseau
Socket TCP
Les sockets sont les éléments du système d'exploitation qui permettent à plusieurs machines de communiquer par l'intermédiaire du réseau.
On peut lire et écrire sur une socket via des flux d'entrée/sortie, exactement comme pour les entrées/sorties console.
Côté serveur
Pour créer une socket en écoute sur un port (ici le port 3000), on va utiliser la classe ServerSocket
:
La méthode accept
de la ServerSocket
va permettre d'attendre la connexion d'un client sur le port :
La méthode accept
nous donne la socket pour communiquer spécifiquement avec le client qui s'est connecté. On peut récupérer les flux d'entrée/sortie pour communiquer avec lui via getInputStream
pour l'entrée, et getOutputStream
.
Pour l'entrée, c'est-à-dire le flux de données qui vient du client (envoyée au serveur par le client), on utilise un BufferedReader
qui nous permet d'écrire simplement du texte ligne par ligne :
Pour la sortie, c'est-à-dire le flux de données qui sont envoyées par le serveur au client, on utilise un PrintWriter
qui nous permet de lire simplement du texte ligne par ligne :
Côté client
Dans notre application cliente, on peut maintenant utiliser la classe Socket
pour se connecter :
De la même façon que pour le serveur, on peut récupérer les flux entrée/sortie de la socket.
Pour l'entrée, c'est-à-dire le flux de données qui vient du serveur (envoyée au client par le serveur) :
Pour la sortie, c'est-à-dire le flux de données qui sont envoyées par le client au serveur :
Communications client-serveur
Pour communiquer sur les flux d'entrée/sortie des sockets, on fait des appels à readLine
et println
. Attention ! Comme l'appel à accept
de la socket serveur, ces appels sont bloquant le temps de la communication : un readLine
est bloquant tant qu'on a pas eu un println
de l'autre côté et vice-versa.
Afin de gérer plusieurs clients en même temps, il faut donc recourir à de la programmation parallèle.
Voyons comment on peut faire ça en implémentant une application de chat basique
Serveur de chat
La logique du code est la suivante : on attend continuellement de recevoir un nouveau client via accept
, lorsque cela arrive, on démarre un thread qui va gérer la communication avec le client, pour que le thread courant puisse continuer à être ouvert à de nouvelles connexions. On ouvre le flux de sortie sur le nouveau client pour le stocker afin qu'il soit accessible dans la méthode qui gère les intéractions client, afin de pouvoir diffuser les messages à tous.
Pour la gestion des interactions client :
On ouvre le flux d'entrée du client, et on va continuellement attendre de nouveaux messages. Quand on reçoit un message du client, on va l'envoyer sur le flux de sortie de tous les clients actuellement connectés.
La méthode main du serveur est très simple :
Client de chat
La méthode connect
a une logique assez simple, se connecter au serveur via Socket
, ouvrir les flux d'entrée/sortie, et lancer l'écoute du message sur un thread.
La méthode exécutée par le thread va être à l'écoute des messages du serveur et les afficher sur le flux d'affichage. La méthode pour envoyer un message écrit ce dernier dans le flux de sortie vers le serveur.
Et enfin la méthode main
:
La logique est de créer le client en lui fournissant comme flux d'affichage System.in
puis d'attendre continuellement une entrée utilisateur pour envoyer des messages.