17
TP Développement Réseau n°3 : Jeu du pendu © 2012 tv <[email protected]> - v.1.0 Sommaire La couche Application 2 Rôle .................................................. 2 Choix du protocole de transport ................................... 2 Principe de base ........................................... 3 Travail demandé : le jeu du pendu 4 Première partie : élaboration du protocole ............................. 4 Principe du jeu ......................................... 4 Déroulement d’une partie ................................... 4 Variantes ............................................ 4 Identification des rôles ..................................... 5 Modèle réseau .......................................... 5 Structure des messages de la couche Application ....................... 6 Côté client ............................................ 6 Côté serveur ........................................... 6 Diagrammes des échanges ................................... 7 Tests de validation ....................................... 7 Deuxième partie : mise en oeuvre sous Qt ............................. 7 Le module QtNetwork ..................................... 7 Les classes fournies ....................................... 8 Présentation de la classe QTcpSocket ............................. 8 Mise en oeuvre de la classe QTcpSocket ............................ 9 Troisième partie : réalisation du programme ............................ 17 L’objectif est de programmer un jeu du pendu en réseau à partir des sockets TCP/IP en mode connecté. 1

TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TP Développement Réseau n°3 : Jeu du pendu

© 2012 tv <[email protected]> - v.1.0

Sommaire

La couche Application 2Rôle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Choix du protocole de transport . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Principe de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Travail demandé : le jeu du pendu 4Première partie : élaboration du protocole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Principe du jeu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4Déroulement d’une partie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4Variantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4Identification des rôles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5Modèle réseau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5Structure des messages de la couche Application . . . . . . . . . . . . . . . . . . . . . . . 6Côté client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6Côté serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6Diagrammes des échanges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7Tests de validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

Deuxième partie : mise en oeuvre sous Qt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7Le module QtNetwork . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7Les classes fournies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8Présentation de la classe QTcpSocket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8Mise en oeuvre de la classe QTcpSocket . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

Troisième partie : réalisation du programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

L’objectif est de programmer un jeu du pendu en réseau à partir des sockets TCP/IP enmode connecté.

1

Page 2: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

LA COUCHE APPLICATION

La couche Application

Rôle

Cette couche est l’interface entre l’application utilisateur et le réseau. Elle va apporter à l’uti-lisateur les services de base offerts via le réseau, comme par exemple le transfert de fichier, la messagerie ...

Rappel : l’application côté client demande un service et l’application côté serveur rend le service.

Les protocoles de la couche Application sont souvent orientés caractères pour des raisons de représentationdes données à échanger. Les protocoles orientés caractères sont les plus simples à mettre en oeuvre car ils ne

nécessitent pas de protocoles supplémentaires pour la représentation des données dans des formats incompatibles(cf. little endian vs big endian, int vs �oat, ...).

Cette couche contient donc tous les protocoles de haut niveau, comme par exemple Telnet, TFTP (TrivialFile Transfer Protocol), SMTP (Simple Mail Transfer Protocol), HTTP (HyperText Transfer Protocol),FTP (File Transfer Protocol) ...

Il est évidemment aussi possible d’implémenter ses propres protocoles en fonction des ses besoins etservices.

Choix du protocole de transport

Le point important pour la couche Application est le choix du protocole de transport à utiliser.

Rappel : TCP permet une communication en mode connecté et UDP en mode non connecté.

Par exemple, TFTP (surtout utilisé sur réseaux locaux) utilisera UDP, car on part du principe que lesliaisons physiques sont suffisamment fiables et les temps de transmission suffisamment courts pour qu’iln’y ait pas d’inversion de paquets à l’arrivée. Ce choix rend TFTP plus rapide que le protocole FTP quiutilise TCP. A l’inverse, SMTP utilise TCP, car pour la remise du courrier électronique, on veut quetous les messages parviennent intégralement et sans erreurs.

TP Développement Réseau n°3 : Jeu du pendu 2 / 17 © 2012 tv <[email protected]>

Page 3: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

LA COUCHE APPLICATION

Protocole Avantages InconvénientsTCP fiable (données acquittées et réémises si non re-

çues), permet de traiter des gros volumes de don-nées en utilisant la segmentation

lent car adapte le débit des données envoyées àla bande passante disponible (contrôle de flux etde congestion), complexe à mettre en oeuvre (no-tamment le multi-clients côté serveur), utilisationdu broadcast et multicast impossible

UDP simple (pas de connexion, pas d’états entre leclient et le serveur), économique en bande pas-sante (en-tête de 8 octets), sans contrôle de conges-tion donc UDP peut émettre sans attendre

pas d’acquittement donc pas de garantie de bonacheminement, pas de détection de pertes doncpas retransmission possible, pas de contrôle deflux et donc risque de saturation des tampons (buf-fers), pas de séquencement donc les datagrammespeuvent être traités dans le désordre

En résumé, TCP est considéré comme �able mais lent. Et inversement, UDP est rapide mais peu �able.

Les applications utiliseront TCP car :– gros volume de données et peu sensible au débit– besoin d’un service fiable (donc pas de tolérance aux pertes)– pas besoin du multicast ni du broadcast

Les applications utiliseront UDP car :– faible volume de données et sensible au débit– pas besoin d’un service fiable (donc tolérance aux pertes)– besoin du multicast ou du broadcast

90% des services d'Internet utilisent TCP !

Principe de base

Rappel : Un protocole rend possible le dialogue entre des processus différents au sein d’un réseau.

De manière générale, un protocole de communication définit l’ensemble des procédures (ou règles) pourréaliser une communication :– Le dictionnaire : les primitives (demande connexion, acquittement, ...)– Le scénario du dialogue : enchaînement des primitives (diagramme de l’échange)– Les modalités : taille et représentation des informations, temps d’attente, etc ...– Les messages échangés : les différents champs (taille et contenu)

Un protocole est toujours décomposé en deux parties :– le PCI (Protocol Control Information) : un en-tête (header) décrivant le protocole– les DATA (DONNÉES) : une suite d’octets en provenance de la couche immédiatement supérieure

Un protocole de la couche Application permet l'échange de messages.

TP Développement Réseau n°3 : Jeu du pendu 3 / 17 © 2012 tv <[email protected]>

Page 4: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

Travail demandé : le jeu du pendu

L’objectif est de programmer un jeu du pendu en réseau à partir des sockets TCP/IP en mode connecté.Il vous faudra définir un protocole de couche application pour permettre un dialogue entre le client et leserveur.Vous travaillerez en équipe de 3 pour la définition du protocole et les tests. Par contre, chacun écrira sonprogramme. Si le protocole est bien défini et respecté, les programmes pourront fonctionner correctementau sein même d’une équipe.Un numéro de port pour le serveur sera attribué par équipe :– équipe n°1 −→ 5001,– équipe n°2 −→ 5002,– ...

Une présentation du protocole dé�ni sera faite par l'équipe oralement en classe.

Première partie : élaboration du protocole

Principe du jeu

Le pendu est un jeu consistant à trouver un mot en devinant quelles sont les lettres qui le composent. Lejeu se joue traditionnellement à deux. On a un nombre maximum de tentatives (qui correspondent audessin du pendu ) pour découvrir ce mot mystère.

Déroulement d’une partie

Les deux joueurs dans cet exemple s’appellent A et B.B choisit un mot et fabrique le mot à découvrir : les lettres composant le mot sont remplacées par destirets sauf pour la première et la dernière lettre.A propose une lettre.La lettre fait-elle partie du mot ?– Oui : B l’inscrit à sa place autant de fois qu’elle se trouve dans le mot.– Non : B dessine le premier trait du pendu (un coup joué et perdu).

Le jeu se poursuit jusqu’à ce que :– A gagne la partie en trouvant toutes les lettres du mot ou en le devinant correctement.– A perd la partie lorsque le nombre de coups joués et perdus est égal au nombre de coups maximumpour découvrir le mot.

– A abandonne la partie (que fait B ? ...)

Variantes

Il existe des variantes :Le nombre de coups maximum peut varier aussi en fonction du nombre de traits qui composent le dessin.On peut par exemple augmenter leur nombre en dessinant pendant la partie non seulement le pendu,mais aussi la potence, ce qui augmenterait les chances du joueur.

TP Développement Réseau n°3 : Jeu du pendu 4 / 17 © 2012 tv <[email protected]>

Page 5: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

Il serait possible d’envisager que le joueur propose aussi la position de la lettre ce qui augmenterait ladifficulté du jeu. Ou qu’il ait un temps limite pour découvrir le mot masqué ...Dans ces variantes, il apparaît la possibilité d’intégrer un niveau de difficulté pour ce jeu (de débutant àexpert par exemple). Le choix des mots à découvrir peut aussi être lié au niveau de la partie. D’autrepart, on pourrait instaurer des choix de mots suivant des thèmes.Évidemment, tout ceci influencera l’élaboration d’un protocole.

Identification des rôles

Dans une architecture client/serveur, il est important d’identifier les rôles :– Le client : « celui qui demande le service ».– Le serveur : « celui qui offre le service ».Question 1. Quel service est rendu par le serveur ?

Réponse : Ici, le service est de « jouer une partie du jeu du pendu ».

Question 2. Que demande le client ?

Réponse : Le client demande à jouer une partie du jeu du pendu.

Question 3. Que répondra le serveur à la demande du client ?

Réponse : Le serveur lui répondra qu’il accepte (ou non) sa demande en lui proposant unmot mystère à découvrir en un nombre maximum de coups.

Question 4. Qu’est-ce qui est donc à la charge du serveur ?

Réponse : Si le serveur accepte de « jouer », il a la charge de choisir un mot à découvrir et dele proposer au client qui a émis la demande.

Question 5. Qui du serveur ou du client fixe les règles du jeu ?

Réponse : C’est le serveur qui fixe les « règles du jeu » en déterminant et contrôlant parexemple le nombre de coups maximum pour le découvrir.

Modèle réseau

Ici, le choix se porte sur le modèle DoD pour faire fonctionner ce jeu en TCP/IP.Question 6. Compléter le modèle DoD ci-dessous en chosissant notamment un protocole de transport ?

Couche ProtocoleApplicationTransportRéseauInterface

Question 7. Dans ce modèle, que reste-t-il à définir ?

Réponse : Le protocole de la couche Application qui implémente le service « jeu du pendu ».

TP Développement Réseau n°3 : Jeu du pendu 5 / 17 © 2012 tv <[email protected]>

Page 6: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

Structure des messages de la couche Application

Le travail consiste à élaborer la structure des messages échangés par le client et le serveur ainsi queleur séquencement.

Question 8. Le protocole à mettre en oeuvre serat-t-il orienté caractère ou orienté bit ?

Réponse : Ici, il est préférable d’élaborer un protocole orienté caractère.

On conservera les délimiteurs utilisés par les autres protocoles connus de la couche Application (HTTP,FTP, ...) : l'espace comme séparateur de champ et "\r\n" comme délimiteur de �n de message.

Évidemment, on distinguera les messages envoyés par le client de ceux envoyés par le serveur.

On vous fixe les contraintes suivantes dans les messages échangés :– tous les champs seront échangés sous la forme de caractères– toutes les informations de protocoles seront échangées en MAJUSCULE– toutes les lettres et le mot seront échangées en minuscule

Le PCI d'un message pourra avoir une longueur �xe car c'est plus plus simple à gérer.

Côté client

Dans le message qu’il envoie au serveur, le client doit préciser le type de sa requête (ou si vous préférezde sa demande). Le client peut par exemple :– demander à jouer une nouvelle partie– proposer une lettre ou un mot– abandonner la partie en cours– ...

Question 9. Définissez précisément la structure et les champs d’un message envoyé par le client.

N'oubliez pas d'indiquer les valeurs attendues et valides des di�érents champs composant un message.

Côté serveur

Par principe, le serveur reçoit toujours des requêtes (ou si vous préférez des demandes) en provenance duclient.Il est plus prudent de considérer que le serveur peut recevoir des demandes valides ou invalides. Leserveur répondra donc toujours en précisant un code réponse.Les codes réponses seront formatés sur trois caractères (xxx) dont les significations sont :– Le premier chiffre indique le statut de la réponse (1 pour succès ou 2 pour échec)– Le second chiffre et le troisième chiffre précise un code d’erreur (00 à 99) ou 00 en cas de succés

TP Développement Réseau n°3 : Jeu du pendu 6 / 17 © 2012 tv <[email protected]>

Page 7: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

Si le serveur répond avec succés à une demande du client, il renverra toujours un code réponse 1xx sinonil renverra un code erreur compris entre 200 à 299.Le code réponse permettra aussi de gérer l’état de la partie au final. On peut fixer par exemple les codesuivants :– 101 : partie gagnée par le client (le mot a été découvert en un nombre de coups inférieur au maximumfixé)

– 102 : partie perdue par le client (le mot n’a pas été découvert et un nombre maximum de coups a étéatteint)

– 103 : partie abandonnée par le client (est-ce que le mot doit être dévoilé ?)

Question 10. Définissez précisément les codes erreurs renvoyés par le serveur.

Question 11. Définissez maintenant la structure et les champs d’un message envoyé par le serveur.

N'oubliez pas d'indiquer les valeurs attendues et valides des di�érents champs composant un message.

Diagrammes des échanges

Question 12. Définissez précisément les diagrammes qui décrivent : une partie gagnée, perdue, aban-donnée par le client.

Tests de validation

Question 13. En utilisant les outils netcat et telnet, procéder aux tests de validation du protocoledéfini par l’équipe.

Puis faire valider son protocole par votre enseignant lors d'une réunion d'équipe.

Deuxième partie : mise en oeuvre sous Qt

Le module QtNetwork

Le module QtNetwork offre des classes qui vous permettent d’écrire vos propres clients et serveursTCP/IP.Pour inclure les déclarations des classes de ce module, il vous faut utiliser la directive suivante :#include <QtNetwork>

Pour disposer ce module, il vous faut ajouter cette ligne à votre fichier de projet .pro :QT += network

N'oubliez pas de refaire un qmake lorsque vous modi�er un �chier de projet .pro.

TP Développement Réseau n°3 : Jeu du pendu 7 / 17 © 2012 tv <[email protected]>

Page 8: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

Les classes fournies

Qt fournit de nombreuses classes pour la programmation réseau (cf. la documentation de Qt).En résumé, on disposera :– des classes comme QFtp pour les protocoles de la couche Application– des classes de plus bas niveau comme QTcpSocket, QTcpServer et QUdpSocket– des classes de plus haut niveau pour une gestion simplifiée du réseau comme QNetworkConfiguration,

QNetworkConfigurationManager, ...

Ici, on aura juste besoin des classes de base pour l’implémentation des sockets sous Qt soit :La classe QTcpSocket fournit une interface pour le protocole TCP. On peut donc utiliser QTcpSocketpour implémenter des protocoles réseau standard comme POP et SMTP, aussi bien que des protocolespersonnalisés.

Présentation de la classe QTcpSocket

Rappel : la programmation Qt est basée sur le mécanisme des signaux et des slots.La classe QTcpSocket est asynchrone et émet des signaux pour reporter des changements de statuts et deserreurs. Elle repose sur une boucle d’événements pour détecter des données arrivantes et automatiquementenvoyer les données partantes.Les signaux qu’il faut au minimum gérer par connect() côté client :– readyRead() signale que des données ont été reçues et sont prêtes à être lues– connected() signale que la socket est dans l’état connecté– disconnected() signale que la socket est dans l’état déconnecté– error() signale qu’une erreur s’est produite sur la socket

Vous pouvez écrire des données dans le socket avec QTcpSocket::write() et en lire avec QTcpSocket::read().

QTcpSocket possède deux �ux indépendants de données : un pour écrire et l'autre pour lire.

Puisque QTcpSocket hérite de QIODevice, vous pouvez l’utiliser avec QTextStream et QDataStream pourgérer vos données.En lisant depuis un QTcpSocket, vous devez être sûr qu’assez de données sont disponibles en appelantQTcpSocket::bytesAvailable() avant.On appellera la méthode non bloquante QTcpSocket::connectToHost() pour se connecter à un serveur.Une connexion TCP doit être établie vers un hôte distant et un port avant que le transfert de donnéespuisse commencer. Une fois la connexion établie, l’adresse IP et le port du point de communicationdistant sont disponibles avec les fonctions QTcpSocket::peerAddress() et QTcpSocket::peerPort(). Àn’importe quel moment, le point de communication distant peut fermer la connexion et le transfert dedonnées s’arrêtera immédiatement.

TP Développement Réseau n°3 : Jeu du pendu 8 / 17 © 2012 tv <[email protected]>

Page 9: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

Mise en oeuvre de la classe QTcpSocket

Pour la mise en oeuvre de la programmation socket sous Qt, on va partir sur un exemple construit paritérations sans utiliser de composants graphiques.Remarque : un développement itératif s’organise en une série de développement très courts de durée fixenommée itérations. Le résultat de chaque itération est un système partiel exécutable, testé et intégré (maisincomplet).

Étape n°1 : création de la socket et connexion au serveurOn commence par créer un fichier clientTCP-1.pro avec le contenu suivant :QT += core networkTEMPLATE = appTARGET =DEPENDPATH += .INCLUDEPATH += .HEADERS += client-1.hSOURCES += client-1.cpp clientTCP-1.cpp

Le fichier de projet clientTCP-1.pro

L’exemple est basé sur la création d’une classe Client. Pour bénéficier des fonctionnalités Qt, la classeClient héritera de la classe de base QObject et intégrera la macro Q_OBJECT pour bénéficier du mécanismesignal/slot.#ifndef CLIENT_H#define CLIENT_H

#include <QObject>#include <QtNetwork>#include <QDebug>

#define PORT_SERVEUR 5000

class Client : public QObject{

Q_OBJECT

public:Client( QObject *parent=0 );~Client();void demarrer();

private:QTcpSocket *tcpSocket; // la socket

};

#endifclient-1.h

Dans cette première étape, on réalisera :1. l’instanciation d’un objet de la classe QTcpSocket

2. la connexion au serveur avec la méthode connectToHost()

TP Développement Réseau n°3 : Jeu du pendu 9 / 17 © 2012 tv <[email protected]>

Page 10: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

Remarque : Qt fournit une classe QHostAddress pour manipuler l’adresse IP d’une machine.

La définition de la classe Client sera donc la suivante :#include "client-1.h"

Client::Client( QObject *parent/*=0*/ ) : QObject( parent ){

qDebug() << QString::fromUtf8("Instancie un objet QTcpSocket");tcpSocket = new QTcpSocket(this); // 1.qDebug() << QString::fromUtf8("État de la socket :") << tcpSocket->state();

}

Client::~Client(){

qDebug() << QString::fromUtf8("Ferme la socket");tcpSocket->close();

}

void Client::demarrer(){

qDebug() << QString::fromUtf8("Connexion au serveur");//tcpSocket->connectToHost(QHostAddress((QString)"0.0.0.0"), PORT_SERVEUR); // remplacer

0.0.0.0 par l’adresse IP du serveurtcpSocket->connectToHost(QHostAddress::LocalHost, PORT_SERVEUR); // 2. (ici le serveur

sera localhost)qDebug() << QString::fromUtf8("État de la socket :") << tcpSocket->state();

}

client-1.cpp

Il ne reste plus qu’à écrire la fonction principale du programme de test :#include <QApplication>

#include "client-1.h"

int main( int argc, char **argv ){

QApplication a( argc, argv );

Client client;

client.demarrer();

return 0;}

clientTCP-1.cpp

La procédure de test est assez simple. Il suffit de faire successivement :$ qmake$ make

$ ./clientTCP-1

TP Développement Réseau n°3 : Jeu du pendu 10 / 17 © 2012 tv <[email protected]>

Page 11: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

"Instancie un objet QTcpSocket""État de la socket :" QAbstractSocket::UnconnectedState"Connexion au serveur""État de la socket :" QAbstractSocket::ConnectingState"Ferme la socket"

Étape n°2 : vérification du bon fonctionnement de la connexionDans cette deuxième étape, on va intégrer les fonctionnalités propres à Qt en utilisant le mécanismesignal/slot.On commence par créer un fichier clientTCP-2.pro avec le contenu suivant :QT += core networkTEMPLATE = appTARGET =DEPENDPATH += .INCLUDEPATH += .HEADERS += client-2.hSOURCES += client-2.cpp clientTCP-2.cpp

Le fichier de projet clientTCP-2.pro

Rappel : La classe QTcpSocket est asynchrone et émet des signaux pour reporter des changements destatuts et des erreurs. Elle repose sur une boucle d’événements pour détecter des données arrivantes etautomatiquement envoyer les données partantes.Les signaux qu’il faudra au minimum gérer côté client sont :– readyRead() signale que des données ont été reçues et sont prêtes à être lues– connected() signale que la socket est dans l’état connecté– disconnected() signale que la socket est dans l’état déconnecté– error() signale qu’une erreur s’est produite sur la socket

On va donc créer les slots suivants dans la classe Client :#ifndef CLIENT_H#define CLIENT_H

#include <QObject>#include <QtNetwork>#include <QDebug>

#define PORT_SERVEUR 5000

class Client : public QObject{

Q_OBJECT

public:Client( QObject *parent=0 );~Client();void demarrer();

private:QTcpSocket *tcpSocket;

private slots:

TP Développement Réseau n°3 : Jeu du pendu 11 / 17 © 2012 tv <[email protected]>

Page 12: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

void estConnecte(); // pour le signal connected()void estDeconnecte(); // pour le signal disconnected()void recevoir(); // pour le signal readyRead()void gererErreur(QAbstractSocket::SocketError erreur); // pour le signal error()

};

#endifclient-2.h

La définition de la classe Client sera donc la suivante en intégrant la connexion des slots avec connect() :#include "client-2.h"

Client::Client( QObject *parent/*=0*/ ) : QObject( parent ){

qDebug() << QString::fromUtf8("Instancie un objet QTcpSocket");tcpSocket = new QTcpSocket(this);

// La connexion des signaux aux slotsconnect(tcpSocket, SIGNAL(readyRead()), this, SLOT(recevoir()));connect(tcpSocket, SIGNAL(connected()), this, SLOT(estConnecte()));connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(estDeconnecte()));connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(gererErreur(

QAbstractSocket::SocketError)));

}

Client::~Client(){

qDebug() << QString::fromUtf8("Ferme la socket");tcpSocket->close();

}

void Client::demarrer(){

qDebug() << QString::fromUtf8("Connexion au serveur");//tcpSocket->connectToHost(QHostAddress((QString)"0.0.0.0"), PORT_SERVEUR);tcpSocket->connectToHost(QHostAddress::LocalHost, PORT_SERVEUR);

}

void Client::estConnecte(){

qDebug() << QString::fromUtf8("Socket connectée au serveur");}

void Client::estDeconnecte(){

qDebug() << QString::fromUtf8("Socket déconnectée au serveur");}

void Client::recevoir(){

qDebug() << QString::fromUtf8("Des données ont été reçues en provenance du serveur");}

TP Développement Réseau n°3 : Jeu du pendu 12 / 17 © 2012 tv <[email protected]>

Page 13: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

void Client::gererErreur(QAbstractSocket::SocketError erreur){

qDebug() << QString::fromUtf8("Une erreur s’est produite sur la socket : ") << tcpSocket->errorString();

qDebug() << QString::fromUtf8("Erreur : ") << erreur;

// Il est possible de personnaliser le traitement de l’erreur// liste des erreurs : http://doc.qt.digia.com/qt/qabstractsocket.html#SocketError-enum/*switch(erreur){

case QAbstractSocket::HostNotFoundError:// ...break;

case QAbstractSocket::ConnectionRefusedError:// ...break;

case QAbstractSocket::RemoteHostClosedError:// ...break;

default:// ...

}*/}

client-2.cpp

Il ne reste plus qu’à modifier la fonction principale du programme de test pour lui demander de bouclersur la gestions des évènements en appelant a.exec() :#include <QApplication>

#include "client-2.h"

int main( int argc, char **argv ){

QApplication a( argc, argv );

Client client;

client.demarrer();

return a.exec(); // permettra de traiter les signaux}

clientTCP-2.cpp

On va réaliser trois tests pour valider cette deuxième itération :$ qmake$ make

// Test n°1 : il n’y a pas de serveur en écoute sur le port 5000$ ./clientTCP-2"Instancie un objet QTcpSocket""Connexion au serveur"

TP Développement Réseau n°3 : Jeu du pendu 13 / 17 © 2012 tv <[email protected]>

Page 14: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

"Une erreur s’est produite sur la socket : " "Connection refused""Erreur : " QAbstractSocket::ConnectionRefusedError^C

// Test n°2 : il y a un serveur (netcat) en écoute sur le port 5000 et celui envoie desdonnées

$ ./clientTCP-2"Instancie un objet QTcpSocket""Connexion au serveur""Socket connectée au serveur""Des données ont été reçues en provenance du serveur"^C

// Test n°3 : il y a un serveur (netcat) en écoute sur le port 5000 mais celui-ci ferme laconnexion

$ ./clientTCP-2"Instancie un objet QTcpSocket""Connexion au serveur""Socket connectée au serveur""Une erreur s’est produite sur la socket : " "The remote host closed the connection""Erreur : " QAbstractSocket::RemoteHostClosedError"Socket déconnectée au serveur"^C

Étape n°3 : échange des donnéesCommencez par créer la version 3 en renommant les fichiers (.pro, .h et .cpp).On rappelle qu’une communication TCP est bidirectionnelle full duplex et orientée flux d’octets. Il nousfaut donc des fonctions pour écrire (envoyer) et lire (recevoir) des octets dans la socket.

Normalement les octets envoyés ou reçus respectent un protocole de couche APPLICATION. Ici, pourles tests, notre couche APPLICATION sera vide ! C'est-à-dire que les données envoyées et reçues ne

respecteront aucun protocole et ce seront de simples caractères ASCII.

Vous pouvez écrire des données dans le socket avec QTcpSocket::write() et en lire avec QTcpSocket::read()ou QTcpSocket::readAll().Faire communiquer deux processus sans aucun protocole de couche APPLICATION est tout de mêmedifficile ! On va simplement fixer les règles d’échange suivantes :– le client envoie en premier une chaîne de caractères une fois connectée– et le serveur lui répondra "ok"

Ici, on va simplement utiliser le type QByteArray pour l’échange des données. Si vous implémentezun protocole personnalisé pour la couche Application, vous pouvez utiliser aussi QTextStream ouQDataStream pour gérer vos données échangées.

TP Développement Réseau n°3 : Jeu du pendu 14 / 17 © 2012 tv <[email protected]>

Page 15: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

La définition de la classe Client sera donc la suivante en intégrant une amélioration (affichage desinformations sur les points de communication local et distant) et deux ajouts (l’émission et la réceptionde données) :#include "client-3.h"

Client::Client( QObject *parent/*=0*/ ) : QObject( parent ){

qDebug() << QString::fromUtf8("Instancie un objet QTcpSocket");tcpSocket = new QTcpSocket(this);

connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(recevoir()));connect(tcpSocket, SIGNAL(connected()), this, SLOT(estConnecte()));connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(estDeconnecte()));connect(tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(gererErreur(

QAbstractSocket::SocketError)));

}

Client::~Client(){

qDebug() << QString::fromUtf8("Ferme la socket");tcpSocket->close();

}

void Client::demarrer(){

// Par précaution, on désactive les connexions précédentestcpSocket->abort();

qDebug() << QString::fromUtf8("Connexion au serveur");//tcpSocket->connectToHost(QHostAddress((QString)"0.0.0.0"), PORT_SERVEUR);tcpSocket->connectToHost(QHostAddress::LocalHost, PORT_SERVEUR);

}

void Client::estConnecte(){

qDebug() << QString::fromUtf8("Socket connectée au serveur");

qDebug() << QString::fromUtf8("Adresse IP du client : ") + tcpSocket->localAddress().toString();

qDebug() << QString::fromUtf8("Numéro de port du client : ") + QString::number(tcpSocket->localPort());

qDebug() << QString::fromUtf8("Adresse IP du serveur : ") + tcpSocket->peerAddress().toString();

qDebug() << QString::fromUtf8("Numéro de port du serveur : ") + QString::number(tcpSocket->peerPort());

QByteArray message("Hello world !\n"); // représente le message de la couche Applicationqint64 ecrits = -1;

// Envoie du messageecrits = tcpSocket->write(message);switch(ecrits)

TP Développement Réseau n°3 : Jeu du pendu 15 / 17 © 2012 tv <[email protected]>

Page 16: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

{case -1 : /* une erreur ! */

qDebug() << QString::fromUtf8("Erreur lors de l’envoi !"); break;default: /* envoi de n octets */

qDebug() << QString::fromUtf8("Message envoyé : ") << message;qDebug() << QString::fromUtf8("Octets envoyés : ") << ecrits;qDebug() << QString::fromUtf8("Message envoyé avec succès !");

}}

void Client::estDeconnecte(){

qDebug() << QString::fromUtf8("Socket déconnectée au serveur");}

void Client::recevoir(){

QByteArray message;

if (tcpSocket->bytesAvailable() < 0)return;

message = tcpSocket->readAll();

qDebug() << QString::fromUtf8("Des données ont été reçues en provenance du serveur");qDebug() << QString::fromUtf8("Octets reçus : ") << message.size();qDebug() << QString::fromUtf8("Message reçu du serveur : ") << message;

}

void Client::gererErreur(QAbstractSocket::SocketError erreur){

qDebug() << QString::fromUtf8("Une erreur s’est produite sur la socket : ") << tcpSocket->errorString();

qDebug() << QString::fromUtf8("Erreur : ") << erreur;

// Il est possible de personnaliser le traitement de l’erreur// liste des erreurs : http://doc.qt.digia.com/qt/qabstractsocket.html#SocketError-enum/*switch(erreur){

case QAbstractSocket::HostNotFoundError:// ...break;

case QAbstractSocket::ConnectionRefusedError:// ...break;

case QAbstractSocket::RemoteHostClosedError:// ...break;

default:// ...

}*/}

client-3.cpp

TP Développement Réseau n°3 : Jeu du pendu 16 / 17 © 2012 tv <[email protected]>

Page 17: TP Développement Réseau - Jeu du pendutvaira.free.fr/reseaux/tp-sockets-tcp-pendu.pdf · 2012. 11. 25. · LACOUCHEAPPLICATION LacoucheApplication Rôle Cettecoucheestl’interfaceentrel’applicationutilisateuretleréseau.Ellevaapporteràl’uti

TRAVAIL DEMANDÉ : LE JEU DU PENDU

On termine par un test de validation :$ qmake$ make

// on utilise en parallèle un serveur netcat sur le port 5000 :$ ./clientTCP-3"Instancie un objet QTcpSocket""Connexion au serveur""Socket connectée au serveur""Adresse IP du client : 127.0.0.1""Numéro de port du client : 39059""Adresse IP du serveur : 127.0.0.1""Numéro de port du serveur : 5000""Message envoyé : " "Hello world !""Octets envoyés : " 14"Message envoyé avec succès !""Des données ont été reçues en provenance du serveur""Octets reçus : " 3"Message reçu du serveur : " "ok"^C

Pour aller plus loin sur la programmation réseau sous Qt, il vous faudra consulter la documentationofficielle :– Le module network (doc.qt.digia.com/qt/qtnetwork.html et (qt.developpez.com/doc/4.7/programmation-reseau/)

– La classe QTcpSocket (doc.qt.digia.com/qt/qtcpsocket.html)– La classe QAbstractSocket (doc.qt.digia.com/qt/qabstractsocket.html)– La classe QIODevice (doc.qt.digia.com/qt/qiodevice.html)– La classe QByteArray (doc.qt.digia.com/qt/qbytearray.html)– La classe QDataStream (doc.qt.digia.com/qt/qdatastream.html)– La classe QTextStream (doc.qt.digia.com/qt/qtextstream.html)

On peut conseiller de regarder les exemples fournis par Qt (et principalement pour commencer leclient/serveur Fortune) :– Tous les exemples (doc.qt.digia.com/qt/examples-network.html)– Le client Fortune (doc.qt.digia.com/qt/network-fortuneclient.html)– Le serveur Fortune (doc.qt.digia.com/qt/network-fortuneserver.html)

Troisième partie : réalisation du programme

Question 14. Écrire les programmes demandés. Une version graphique du client peut être réalisé.

TP Développement Réseau n°3 : Jeu du pendu 17 / 17 © 2012 tv <[email protected]>