Vous êtes sur la page 1sur 16

client-serveur TCP en Java

ut ut ut

Bilal DJELASSI

Comme promis, voici un petit document qui explique un peu le fonctionnement et la


programmation (trs basique) de deux programmes client-serveur (lun est un client, lautre un
serveur). Ceci est prsent ici en Java, et suivi par une capture des trames qui auront circuls
entre les deux programmes, ainsi que leur analyse (un peu dtaille, elle portera sur le protocole
TCP).
Ce document ne traitera que le protocole TCP (au niveau transport) qui permet de
communiquer en mode connect . Je reviendrai sur a un peu plus loin.
Cest dans le contexte du TCP que je dvelopperai mes ides.
Tout dabord, je rpondrai certaines questions qui peuvent vous tarauder lesprit :
Cest quoi un client ? un serveur ?
Un client, comme un serveur, est tout simplement un programme (ou processus) tournant sur
une machine et qui utilise la pile protocolaire (tout simplement le rseau) pour communiquer
avec dautres programmes. La diffrence qui existe entre un client et un serveur est la manire
de procder pour tablir la connexion :
- Un serveur est passif, il ne prend pas dinitiative, il reste lcoute, en attente dune
demande de connexion.
- Un client est actif, ce qui veut dire quil prend linitiative de contacter un serveur et
demander louverture dune connexion.
Une fois la connexion tablie, la communication entre les deux processus est symtrique,
bidirectionnelle. Chacun peut envoyer ou recevoir des donnes comme bon lui semble (enfin
comme bon nous semble !)
Alors un programme est soit client, soit serveur ?
Non, un programme peut ne pas utiliser le rseau et ses services. Il peut aussi tre client de
plusieurs serveurs (Internet Explorer par exemple), serveur de plusieurs clients, ou alors les deux
(comme les logiciels peer2peer de tlchargement). On peut tout faire quoi.
Comment programme-t-on ce genre de chose ?
Cest faisable en plusieurs langages, mais la complexit varie beaucoup. En C/C++, cela dpend
de la plateforme et de certaines bibliothques, et cest assez complexe. En Java, cest trs
simplifi et trs bien organis.
A-t-on obligatoirement besoin davoir un vrai rseau pour travailler ?
Non. Il existe ce que lon appelle linterface loopback : il sagit dune interface rseau virtuelle
disponible sur tous les systmes dexploitation. Elle porte gnralement ladresse IP 127.0.0.1.
On peut utiliser cette interface mme en nayant aucune connexion un rseau.
Le problme, cest que les donnes qui transitent par cette interface sont traites jusquau
niveau 3 du modle OSI (couche rseau : IP). Les donnes ne sont jamais encapsules dans des
trames Ethernet ou autre Conclusion : on ne peut pas capturer des trames (avec WireShark
par exemple) sur cette interface, mais on peut faire beaucoup de choses intressantes !

Pour capturer les trames, je vais user de lartifice montr dans le document prcdent (Rseau
virtuel avec VirtualBox). Pour ceux qui ne peuvent pas appliquer ce procd, des fichiers de
captures de trames ( ouvrir avec WireShark) seront fournis.
Bon, commenons maintenant clarifier les ides et fixer un objectif : raliser deux programmes
qui communiquent travers le rseau.
On aura un serveur, et un client. Une fois la connexion tablie, le client lira du texte saisi au
clavier et lenverra au serveur. Ce dernier renverra un message (toujours du texte) en rapport
avec ce quil a reu prcdemment. Pour notre cas, le serveur compte le nombre de caractres
et renvoie une phrase du genre : votre message contient x caractres
Exemple de ce que lon cherche obtenir (en partie) :
Client : hello
Serveur : votre message contient 5 caractres
En bleu : ce que lon saisira au clavier, du ct client
En orange : la rponse du serveur, reue toujours ct client
On utilisera le protocole TCP. Ce protocole tablit une communication entre deux machines, et
cela en mode connect : le protocole sassure que les deux programmes qui souhaitent
communiquer puissent le faire, et que lchange dinformations se droule correctement.
On passera donc par :
- une tape de connexion (au sens TCP)
- un change de donnes (une fois que les machines sont connectes)
- une fermeture de connexion (au sens TCP toujours)
Comment se fait-il que plusieurs programmes utilisent le rseau sans conflit ?
Du moins en ce qui concerne le TCP et lUDP, on dispose de ce que lon appelle des ports. Ce
sont simplement des nombres entiers positifs cods sur 16 bits (ce qui nous fait un total de 216
c--d 65536 possibilits). Chaque nombre est attribu (ou choisi par) un programme dsirant
communiquer en rseau en utilisant ces protocoles.
Donc en tout, pour identifier correctement une connexion, il nous faut 5 paramtres :
- Le protocole : TCP ou UDP
- Ladresse IP du client (de la machine sur laquelle tourne le client)
- Le numro de port du client
- Ladresse IP du serveur (de la machine sur laquelle tourne le serveur)
- Le numro de port du serveur
Lensemble de ces paramtres identifie totalement une connexion (TCP ou UDP). En
programmation, lensemble de ces paramtres constitue une structure de donnes appele
Socket (un Socket ou une Socket, masculin ou fminin, cest pareil). Littralement, cela veut dire
prise en anglais.

On pourra imaginer le rseau informatique comme le rseau de distribution dlectricit :


chaque appareil lectrique vient se greffer sur le rseau en passant par une prise. Ainsi, on
pourra dire que chaque programme voulant communiquer ou transmettre des donnes passe
par une prise rseau quon appelle Socket.
Tout ce que lon a faire, cest crer convenablement la socket, puis lutiliser pour
communiquer. Vous vous souvenez de la diffrence client-serveur ? Cette diffrence se
rpercutera sur la faon de crer la socket.
Dans un premier instant, on utilisera linterface loopback (soit IP=127.0.0.1).
Voici les codes sources (Java) du client (lexplication viendra aprs) :
Fichier : Client.java
// packages input/ouput et network importer
import java.io.* ;
import java.net.* ;
public class Client
{
public static void main(String[] args)
{
// variable/objet du type Socket
Socket s ;
// nos paramtres de connexion : @IP et port du serveur
String server_ip = "127.0.0.1" ;
int
port
= 43210 ;
try
{
// message d'acceuil
System.out.println("
System.out.println("
System.out.println("

(sur cran)
Programme client ") ;
---------------- ") ;
Essai de connection sur : @IP " + server_ip + " PORT " + port);

// cration d'une socket connecter sur le serveur @IP:10.0.0.2 et PORT: 43210


s = new Socket(server_ip,port) ;
// ici, la connexion est tablie
System.out.println(" Connexion tablie ") ;
System.out.println(" ----------------- ") ;
// obtention des flux d'entre et de sortie lis la socket
BufferedReader entree =
new BufferedReader( new InputStreamReader( s.getInputStream() ) ) ;
PrintStream sortie =
new PrintStream( s.getOutputStream() ) ;
// obtention du flux d'entre associ au clavier
BufferedReader clavier =
new BufferedReader( new InputStreamReader( System.in ) ) ;
// communication
while(true)
{
// On affiche un message d'invite sur l'cran
System.out.print("Client : ") ;
// Saisie au clavier
String message ;
message = clavier.readLine();
// envoi du message saisi au clavier
sortie.println(message) ;
sortie.flush();
// on affiche un autre message pour la rponse du serveur
System.out.print("Serveur : ") ;
// rception de la rponse du serveur
String reponse ;
reponse = entree.readLine() ;

// affichage du message du serveur


System.out.println(reponse) ;
// si le message envoy est "bye", coupons la connexion
if( message.equals("bye") )
{
break ;
}
}
// si on atteint ce point, alors on coupera la connexion
s.close() ;
// ici, la connexion est ferme du ct client
System.out.println(" ----------------- ") ;
System.out.println("Connexion ferme du ct client") ;
}
catch(IOException e)
{
System.out.println("OOoops !! Impossible d'tablir ou d'utiliser la connexion !") ;
}
}
}

Explications :
import java.io.* ;
import java.net.* ;

On importe les packages io (pour Input/Output) et net (pour Network). On utilisera des classes
prdfinies en Java pour le rseau et les entres/sorties.
public class Client { }

Tout programme Java doit au moins contenir une classe, elle sappelle ici Client (le nom est
choisi pour tre vocateur, vous pouvez mettre nimporte quel nom pas dj utilis).
public static void main(String[] args) { }

Point dentre principal de notre programme. Ici dbutera lexcution.


Socket s ;

On dclare une variable (ou objet en langage Orient Objet) du type Socket qui existe (prdfini)
dans le package java.net. Pour tablir une connexion TCP, il faudra passer par une socket !
String server_ip = "127.0.0.1" ;
int
port
= 43210 ;

On dclare ici nos paramtres de connexion. Rappelez-vous, il nous faut 5 paramtres :


- Le protocole : TCP dans notre cas. Il est implicitement dfini, car en utilisant la classe
Socket, on travaille toujours en mode connect (TCP  Socket).
- IP/Port source (client) : lIP est connue (pas la peine de la dfinir, elle sera rcupre
automatiquement), et le port peut tre choisi (par le programmeur) ou bien attribu par le
systme dexploitation. On choisira cette dernire option  On na rien coder !!
- IP/Port destination (serveur) : il faudra les prciser. Ce sont les paramtres qui manquent.
Ils sont dclars ci-dessus, et vont tre utiliss dans ce qui suit.
A retenir :
Le client possde toujours tous les paramtres de connexion.

try { }
catch(IOException e) { }

Les oprations douverture de connexion et de communication peuvent rencontrer des


problmes. Les mthodes que lon utilise sont donc susceptibles de lancer ou dclencher des
exceptions. Les plus importantes sont les IOException (Input/Output Exception). Voir un cours
Java pour plus de dtails sur les exceptions.
s = new Socket(server_ip,port) ;

Ici, on tente douvrir une connexion vers le serveur identifi par lIP server_ip et le port port. A
lexcution de ce code des trames TCP sont mises en direction du serveur pour demander
louverture de connexion.
Nous tudierons ces trames un peu plus loin.
A la fin de lexcution de cette ligne, il y a deux cas de figure :
- Soit tout sest bien pass, et on obtient un objet de type Socket qui identifie clairement notre
connexion avec le serveur. On continuera lexcution partir de la ligne suivante.
- Soit un problme est survenu (et il y a tant de causes ) : dans ce cas, une IOException est
leve et on poursuit le programme dans le bloc catch (en affichant un message derreur).
Donc, en rsum, si cette instruction passe, on est connects !!
Ici, un peu de concentration sera ncessaire :
BufferedReader entree = new BufferedReader( new InputStreamReader( s.getInputStream() ) ) ;
PrintStream sortie = new PrintStream( s.getOutputStream() ) ;

La socket s, une fois correctement cre, va nous permettre de communiquer. Le principe en


Java pour lchange de donnes (en gnral, pas uniquement en rseau) est lutilisation des
flux : pour faire simple, les flux sont comme des canaux par lesquels transitent des donnes (en
loccurrence des octets).
Ainsi, toute opration dentre/sortie seffectue travers des flux. Par exemple, laffichage vers
lcran (la sortie standard plus exactement) se fait via le clbre flux System.out . La lecture de
ce qui entr au clavier se fait par le non moins clbre flux System.in .
On distingue plusieurs types de flux (prdfinis en Java), et on peut les classer de diffrentes
manires :
- Suivant le sens : il existe des flux dentre et des flux de sortie
- Suivant le type de donnes : octets, caractres, chanes de caractres, fichiers, objets mme
- etc
On retiendra pour linstant quil existe des flux dentre et de sortie.
Ainsi, comme une connexion sert communiquer, et que lon peut communiquer dans les deux
sens (une fois la connexion tablie), on peut rcuprer deux flux rattachs la socket :
- Un flux dentre (de type InputStream) : pour le sens serveur  client
- Un flux de sortie (de type OutputStream) : pour le sens client  serveur

On les rcupre par deux mthodes de la classe Socket :


- Lentre est donne par : s.getInputStream() (du type InputStream)
- La sortie quant elle par : s.getOutputStream() (du type OutputStream)
Les donnes manipules par ces flux sont des octets (InputStream et OutputStream sont des
flux basiques, les plus simples quoi). Pour pouvoir transmettre du texte, on devra les faire
voluer vers des flux plus adapts au texte.
On construit donc des flux amliors partir des flux simples avec les longues instructions
donnes plus haut. On utilise les constructeurs (cest normal, on construit) des classes
prdfinies dans le package java.io pour faire les transformations suivantes :
InputStream  InputStreamReader  BufferedReader
OutputStream  PrintStream
Une fois ces flux amliors, on utilisera deux mthodes pour envoyer et recevoir du texte :
- println : pour crire du texte sur le PrintStream (il est fait pour quon puisse printer)
- readLine : pour lire du texte sur le BufferedReader (cest bien un reader, non ?)
Nous verrons a plus loin.
BufferedReader clavier = new BufferedReader( new InputStreamReader( System.in ) ) ;

Ca rappelle quelque chose Cest le mme tour de passe-passe que celui vu plus haut : on
amliore le flux System.in reli au clavier. Mais pourquoi namliore-t-on pas le System.out ?
parcequil est trs utilis, et que devoir lamliorer dans chaque programme serait une perte de
temps pour les programmeurs. Ainsi a-t-on dcid de le mettre prt lemploi.
A ce stade, nous travaillons avec 4 flux :
- Flux dentre rseau (nomm entree)
- Flux de sortie rseau (nomm sortie)
- Flux dentre clavier (nomm clavier)
- Flux de sortie cran (nomm System.out)
while(true) { }

Ici, on boucle linfini en ritrant les tapes suivantes :


String message ;
message = clavier.readLine();

On lit ce que veut transmettre lutilisateur (au niveau du Client) On met la ligne saisie dans la
variable chane de caractres message ,
sortie.println(message) ;
sortie.flush();

On crit ce message sur le flux de sortie rseau (donc le texte sera transmis au serveur), la
deuxime ligne ordonne de vider la mmoire tampon utilise pour stocker le texte en attente de
transmission.

String reponse ;
reponse = entree.readLine() ;

Ici, on lit ce que nous transmet le serveur sur le flux dentre rseau. On met le rsultat dans la
variable chane de caractre reponse ,
System.out.println(reponse) ;

Et enfin, on affiche cette rponse sur lcran.


if( message.equals("bye") )
{
break ;
}

Pour mettre fin notre conversation avec le serveur, on a rajout ces petites lignes : si le texte
entr est bye , alors on sort de la boucle infinie.
s.close() ;

En dehors de la boucle while (c--d lorsquon aura saisi bye ), on ferme la connexion avec la
mthode close de la classe Socket. Cela a pour consquence de gnrer des trames particulires
qui mettent fin la connexion. On les verra un peu plus loin.
Cest fini !!
Si vous compilez ce programme et que vous le lancez maintenant, il ne fonctionnera pas car il
ny a pas de serveur lcoute. Mettez le programme de ct et passons au serveur.
La seule diffrence, cest dans la manire dobtenir une socket correctement initialise. On verra
uniquement des petites modifications au niveau du programme serveur :
Fichier : Serveur.java
// packages input/ouput et network importer
import java.io.* ;
import java.net.* ;
public class Serveur
{
public static void main(String[] args)
{
// variable/objet du type ServerSocket
ServerSocket server_s ;
// variable du type Socket
Socket s ;
// nos paramtres de connexion : port du serveur uniquement
int
port
= 43210 ;
try
{
// message d'acceuil
System.out.println("
System.out.println("
System.out.println("

(sur cran)
Programme Serveur ") ;
----------------- ") ;
Attente de connection sur : PORT " + port) ;

// cration d'une ServerSocket ouvrant le port 43210


server_s = new ServerSocket(port) ;
// attente de connexion sur le serveur sur le port 43210
s = server_s.accept() ;

// ici, la connexion est tablie


System.out.println(" Connexion tablie ") ;
System.out.println(" ----------------- ") ;
// obtention des flux d'entre et de sortie lis la socket
BufferedReader entree =
new BufferedReader( new InputStreamReader( s.getInputStream() ) ) ;
PrintStream sortie =
new PrintStream( s.getOutputStream() ) ;
// communication
while(true)
{
// On affiche un message explicatif l'cran
System.out.print("Client -> Serveur : ") ;
// Rception du message du client
String message ;
message = entree.readLine();
// Affichage du message reu
System.out.println(message) ;
// On confectionne un petite rponse
String reponse = "Ce message contient " + message.length() + " caractres" ;
// Affichage sur cran d'un petit message de rponse au client
System.out.print("Serveur -> Client : ") ;
System.out.println(reponse) ;
// On envoie cette rponse au client
sortie.println(reponse) ;
sortie.flush() ;
// Si le message est "bye", le serveur coupe la connexion
if( message.equals("bye") )
{
break ;
}
}

// si on atteint ce point, le message est "bye"


// on ferme la connexion
s.close();
// ici, la connexion est ferme du ct serveur
System.out.println(" ----------------- ") ;
System.out.println("Connexion ferme du ct serveur") ;
}
catch(IOException e)
{
System.out.println("OOoops !! Impossible d'tablir ou d'utiliser la connexion !") ;
}
}
}

Explication :
Il y a beaucoup de ressemblance, dans le corps du programme. On importe toujours les mmes
packages. La classe sappelle cette fois Serveur. Cest dans le corps du main que de
nouvelles choses apparaissent :
ServerSocket server_s ;
Socket s ;

En plus de la Socket, nous avons une ServerSocket nas-t-on pas dit quil fallait une socket ?
Pourquoi une ServerSocket ?

En fait, le serveur doit indiquer au systme dexploitation (qui gre la pile protocolaire TCP/IP)
quil souhaite couter ce qui arrive en destination dun port particulier (celui que le serveur
dsire ouvrir). On parle d ouverture de port .
La ServerSocket sert justement faire cette configuration. Passons en revue nos 5 paramtres de
connexion :
- Le protocole : TCP (implicitement connu, car on utilise la classe Socket qui ne fait que a)
- LIP/port source (serveur) : IP connue, et le port aussi (car on souhaite louvrir)
- LIP/port destination (client) : tous deux non connus.
Que va-t-on faire ? Deux choses :
- Demandez louverture du port dsir au niveau du serveur
- Attendre quun client nous contacte (contacte le serveur). Lorsquun client contacte le serveur,
les trames reus contiennent les donnes manquantes pour fabriquer la socket : on extrait des
trames de demande de connexion provenant du client ladresse IP et le port du client.
On fabrique la socket, et on est prt communiquer !!
int

port

= 43210 ;

Voil le port que notre serveur va ouvrir Enfin va tenter douvrir, car on ne sait jamais, il peut y
avoir des problmes. Toutes les instructions suivantes sont dans un bloc try :
server_s = new ServerSocket(port) ;

Ici, on demande douvrir un port (en loccurrence 43210 : jai choisi ce port dans la zone des
ports > 1024). A noter quun serveur est passif, aucune trame nest gnre ici.
Si linstruction russit, le port est ouvert et associ au programme serveur.
s = server_s.accept() ;

Ici, on attend (au vrai sens du terme) quun client se connecte. Linstruction est bloquante, c--d
quon reste en ce point jusqu ce quun client arrive et se connecte.
La mthode accept appartient la classe ServerSocket. Applique lobjet s_server, elle renvoie en
cas de succs une socket valide (en compltant les infos manquantes : IP client et port client).
La suite est comme pour le client. On nutilisera pas le flux associ au clavier. On boucle linfini
en passant par ces tapes :
- On lit le message envoy par le client,
- On laffiche lcran (du serveur),
- On confectionne un rponse : jai choisi de compter le nombre de caractres (y compris les
espaces) et denvoyer en rponse le texte : Ce message contient x caractres
- On affiche la rponse lcran (du serveur),
- On transmet cette rponse au client.
Si on reoit le message bye , on ferme la connexion.
Voil ! cest fini.

Compilez le programme serveur. Le programme serveur doit tre lanc avant le client. Vous
pouvez observez (parfois) au lancement du serveur un message dalerte de votre pare-feu : un
pare-feu est un logiciel qui joue un peu le rle dun gendarme, on contrlant qui fait quoi avec
les connexions. Il vite de rpondre certaines trames et messages douteux, et contrle qui
ouvre des ports. Pour fonctionner, vous devez autoriser votre serveur ouvrir les ports. Cela est
propos facilement sur votre pare-feu.
Lancez votre client, et miracle, ils sont connects.
Un dtail : vous pouvez travailler avec nimporte quel environnement de dveloppement Java. Je
fais mes tests sous Eclipse, mais vous pouvez choisir ce que vous voulez
Voici une capture dcran (jai lanc des invites de commandes) :

Fig1. Client connect un serveur, en utilisant linterface loopback (sur la mme machine)
Remarque : pour les caractres accentus qui saffiche mal, il y a une explication et une petite
solution (valable aussi en C/C++). Prochainement
Maintenant, si on veut voir les trames, ce nest pas possible . (possible sous Unix, mais avec
une certaine complexit pas vidente mettre en uvre).
Comme solution (il peut en exister dautres et des meilleures, mais bon je me contente de a), je
propose dutiliser le rseau virtuel mis en place avec VirtualBox (document prcdent).
Si vous navez pas lu le document prcdent, je vous invite le faire.
Jaurai donc deux machines : Une sous Vista (mon OS) et une sous XP.

La machine sous Vista contiendra le client, et lautre le serveur.


La configuration IP et Ethernet sont les suivantes :
- Ct client (Vista) :
@IP
: 10.0.0.1 ( configurer ncessairement soi-mme !)
@MAC : 00-FF-17-21-DE-41 (rgle automatiquement, peut tre diffrente)
- Ct serveur (XP) :
@IP
: 10.0.0.2 ( configurer ncessairement soi-mme !)
@MAC : 08-00-27-1D-A0-E9 (rgle automatiquement, peut tre diffrente)
Nous ferons simplement une petite modification au niveau du client : mettre 10.0.0.2 la place
de 127.0.0.1 et recompiler.
Voici un petit diagramme qui rsume ltat de nos programmes connects :
Socket
@IPsource = 10.0.0.1
Port source : xyz
@IPdestinat = 10.0.0.2
Port destint :43210

Socket
InputStream

InputStream

OutputStream

OutputStream

Client TCP
(sous Vista)

@IPsource = 10.0.0.2
Port source : 43210
@IPdestinat = 10.0.0.1
Port destint : xyz

Serveur TCP
(sous XP)

On peut lancer WireShark sur nimporte laquelle des machines. On capturera les trames Ethernet
qui circulent entre les programmes.
Une fois chaque programme mis sur une machine, jobtiens la trace dexcution suivante (le
texte que jai entr est en bleu, ceci nest quun exemple, vous pouvez faire ce que vous voulez) :

Fig2. Trace dexcution du client

Fig3. Trace dexcution du serveur

Ce qui sest pass :


- Le client sest connect au serveur (situ en @IP 10.0.0.2 et port 43210)
- Un change de trois messages (hello, how are you, bye) et trois rponses
- Une fermeture de connexion
Une capture de trames lance en mme temps a t ralise. Une copie de ces trames est
disponible sur le fichier client_serveur_tcp.pcap , ouvrir avec WireShark.
Enfin, on arrive la deuxime partie Limage ci-dessous montre le total de 27 trames
changes lors de lexcution de nos programmes. Le nombre 27 nest pas fig (vous pouvez
avoir plus ou moins), mais lordre gnral est toujours le mme.
Aprs avoir lanc le serveur (le client pas encore lanc), aucune trame na t mise (le serveur
ne prend pas linitiative, il ne peut pas car il na pas tous les paramtres de connexion).
Une fois le client lanc, on observe un change de 5 trames :
- 2 trames ARP (Address Resolution Protocol)
- 3 trames TCP
Pourquoi des trames ARP ? parce que le client ne connat que ladresse IP du serveur, pas
ladresse MAC qui le mnera lui. Le client cherche en utilisant lARP dterminer ladresse
MAC qui les trames quil enverra seront destines.

Fig4. Trames captures entre le client et le serveur


Je ne prsenterai pas ici les dtails de chaque protocole
Trame 1 : Requte ARP
0000
0010
0020

ff ff ff ff ff ff 00 ff
08 00 06 04 00 01 00 ff
00 00 00 00 00 00 0a 00

17 21 de 41 08 06 00 01
17 21 de 41 0a 00 00 01
00 02

........ .!.A....
........ .!.A....
........ ..

En gros, cela se traduit par (lecture squentielle du dbut jusqu la fin) :


- @MAC destination
:
ff ff ff ff ff ff  Tout le monde (= le domaine de diffusion)
- @MAC source
:
00 ff 17 21 de 41  Le client
- Protocole Rseau
:
08 06  ARP
- Adressage physique
:
00 01  Ethernet
- Adressage logique
:
08 00  IP
- Longueur @physique :
06  6 octets (le cas des adresses MAC)
- Longueur @logique
:
04  4 octets (le cas dIPv4)
- Type ARP
:
00 01  requte de rsolution @IP vers @MAC
- @Physique source
:
00 ff 17 21 de 41  Le client
- @Logique source
:
0a 00 00 01  10.0.0.1 en dcimal : LIP du client
- @Physique destination :
00 00 00 00 00 00  Inconnue, cest elle quon cherche
- @Logique destination :
0a 00 00 02  10.0.0.2 en dcimal : LIP du serveur
On peut traduire tout cela en langage humain : Salut tout le monde, je suis la machine
10.0.0.1, jhabite en 00 ff 17 21 de 41, je cherche la machine 10.0.0.2, quelle me dise o puis-je
la trouver !

En rponse cette requte que reoit la machine 10.0.0.2 (et toutes les autres machines), elle
formule une rponse convenable :
Trame 2 : Rponse ARP
0000
0010
0020
0030

00
08
00
fa

ff
00
ff
db

17
06
17
9f

21
04
21
df

de
00
de
00

41
02
41
00

- @MAC destination
- @MAC source
- Protocole Rseau
- Adressage physique
- Adressage logique
- Longueur @physique
- Longueur @logique
- Type ARP
- @Physique source
- @Logique source
- @Physique destination
- @Logique destination
- Bourrage

08
08
0a
0d

:
:
:
:
:
:
:
:
:
:
:
:
:

00
00
00
0a

27
27
00
4b

1d
1d
01
45

a0
a0
6b
42

e9 08 06 00 01
e9 0a 00 00 02
00 32 33 50 18
46

...!.A..
........
...!.A..
........

'.......
'.......
..k.23P.
KEBF

00 ff 17 21 de 41  Le client
08 00 27 1d a0 e9  Le serveur
08 06  ARP
00 01  Ethernet
08 00  IP
06  6 octets (le cas des adresses MAC)
04  4 octets (le cas dIPv4)
00 02  rponse une requte de rsolution @IP vers @MAC
08 00 27 1d a0 e9  Le serveur
0a 00 00 02  10.0.0.2 en dcimal : LIP du serveur
00 ff 17 21 de 41  Le client
0a 00 00 01  10.0.0.1 en dcimal : LIP du client
6b 00 32 33 50 18 fa db 9f df 00 00 0d 0a 4b 45 42 46

Remarque : certaines trames prsentent un bourrage, dautres non Les tailles des trames
semblent aussi petites Je nai pas encore rsolu cette question.
A ce stade, la machine client connat l@MAC de la machine serveur. On peut maintenant passer
ltablissement de connexion TCP. Cela se fait en trois tapes (on parle de poigne de mains
en trois temps) :
- Trame 3 : Client  Serveur avec les indicateurs : SYN
+ Seq Num :
b6 c9 78 c0 = 3066656960 en dcimal
+ Ack Num :
00 00 00 00 = non encore initialis
- Trame 4 : Serveur  Client avec les indicateurs : SYN & ACK
+ Seq Num :
f9 38 9b 12 = 4181236498 en dcimal
+ Ack Num :
b6 c9 78 c1 = 3066656961 en dcimal
- Trame 5 : Serveur  Client avec les indicateurs : ACK
+ Seq Num :
b6 c9 78 c1 = 3066656961 en dcimal
+ Ack Num :
f9 38 9b 13 = 4181236499 en dcimal

SYN
seq = x

SYN , ACK
seq = y , ack = x+1

Voici un diagramme qui illustre cela :


On voit aussi les N de ports utiliss pour la communication :
- 43210 : pour le serveur
- 49807 : pour le client

ACK
seq = x+1 , ack = y+1

Fig5. Etablissement de connexion TCP


Client

Serveur

Ensuite, les changes de donnes commencent. Les champs SeqNum et AckNum sont
incrments chaque fois du nombre doctets transmis et reus correctement. Vous pouvez
observer les trames 6 23 sous WireShark, en analysant le contenu de la colonne info. Les
indicateurs, le SeqNum (sequence number), le AckNum (acknowlegement number), et la
longueur des donnes transportes (len) sont donnes relativement au premires valeurs x et y
utilises lors de ltablissement de connexion : il est not 6 au lieu de x+6 = 3066656966 par
exemple.
Enfin, dernire tape cruciale, la fermeture de connexion. Bizarrement, la fermeture de
connexion ncessite 4 changes de trames, une fermeture et confirmation ct client, et encore
une fermeture et confirmation ct serveur.
FIN & autres
ack = v

Voici un diagramme qui explique un peu cela :

ACK
seq = v , ack = u

Linitiative de fermeture peut tre prise par nimporte quel


ct (client ou serveur).

FIN & autres


ack = u

Les trames 24 27 illustrent ce cas.

ACK
seq = u , ack = v+1

Fig6. Fermeture de connexion TCP

Client

Serveur

PS : Il se peut quil y ait des erreurs ! Merci de les signaler !!