Communication TCP avec TcpClient et TcpListener
Date de publication : 3/11/2008 , Date de mise à jour : 3/11/2008
Par
Sabri Koffler (Accueil) (Blog)
Les classes TcpClient et TcpListener de .net 2.0 offrent une technique de
programmation pratique de communication TCP
INTRODUCTION
I. La classe TcpClient
I-A. Construire un objet TcpClient
I-B. Obtenir un objet NetworkStream
I-B-1. Remarque sur la notion client et serveur
I-B-2. L'objet NetworkStream( System.Net.Sockets)
I-C. La méthode Write du NetworkStream
I-D. La méthode Read du NetworkStream
I-D-1. Définition : synchrone
II. La classe TcpListener
II-A. Création de l'objet TcpListener
II-B. Le démarrage de l'écoute
II-C. L'arrêt de l'écoute
III. Source d'exemple
IV. CONCLUSION
. Remerciements
INTRODUCTION
Le .net framework 2.0 fournit une manière de communication directe en TCP,
sans forcément passer par des sockets. C'est une méthode un peu moins bas
niveau que les sockets, mais qui reste un équivalent. Il s'agit des classes
TcpClient et TcpListener. Elles peuvent être remplacées chacune par la
classe Socket( System.Net.Sockets), et utilisées en même temps( par
exemple un TcpListener et une Socket en client, ou bien une Socket en écouteur
et un TcpClient en client).
I. La classe TcpClient
Comme l'explique clairement MSDN, la classe TcpClient(System.Net.Sockets,
dll : System) nous procure une manière de se connecter à un écouteur. Elle permet
aussi de recevoir un flux de données et d'en émettre un à un
écouteur, tout ceci se faisant en mode synchrone bloquant. Remarque :
l'espace de nom, System.Net.Sockets, nous montre qu'il s'agit bien de
l'équivalent des sockets, mais avec un enrobage objet plus sympathique, et
qui paraît moins bas niveau. Un écouteur est un processus qui écoute les
demandes de connexion entrantes (entrantes car on cherche à se connecter au
serveur, donc sens client->serveur). On peut créer un écouteur notamment
avec la classe TcpListener, que nous verrons bientôt, mais aussi avec la
classe Socket (System.Net.Sockets) (ce qui prouve d'ailleurs que TcpClient
équivaut aux sockets !).
I-A. Construire un objet TcpClient
Constructeur intéressant :
TcpClient monClientTcp = new TcpClient(nomServeur, port);
|
nomServeur est le nom DNS de l'ordinateur (le nom en toutes lettres que vous lui avez donné),
mais cela peut être aussi son adresse IP.
Le numéro de port est le numéro de port de l'ordinateur hôte.
Ce constructeur essaye de se connecter dès que vous l'utilisez.
Pour que la connexion puisse s'établir, il faut, bien entendu, qu'un objet TcpListener soit
à l'écoute, ou encore un objet de la classe Socket(System.Net.Sockets).
Fermeture : monClientTcp.Close( ) ;
Exceptions intéressantes pouvant être déclenchées:
(System.Net.Sockets.).SocketException
I-B. Obtenir un objet NetworkStream
Une fois la connexion établie, vous avez besoin d'un objet de la classe
NetworkStream pour pouvoir émettre ou recevoir des données.
I-B-1. Remarque sur la notion client et serveur
Attention, les termes client/serveur ne signifient
pas que le client ne peut pas émettre, ou que le serveur ne peut pas recevoir. Le client,
comme le serveur, peut émettre ET recevoir des données. La seule différence entre les deux,
c'est que l'écouteur( le serveur) est toujours en attente d'une demande de connexion d'un
client. Donc ce processus écouteur est toujours actif. Alors que le client peut avoir une
vie limitée : il se connecte quand il veut, et s'arrête quand il le souhaite. Par conséquent,
la notion de serveur et de client existe essentiellement par rapport à la notion de connexion
, et pas par rapport à la capacité d'émettre ou de recevoir des données. Ne croyez donc pas
qu'un serveur ne peut qu'émettre des données, et qu'un client ne peut qu'en recevoir.
Pour ces raisons, je ne préfère pas utiliser des termes comme " émetteur " pour désigner
un TcpListener, ni utiliser " récepteur " pour désigner un TcpClient. Je préfère appeler
client Tcp un objet TcpCLient, et serveur Tcp ( ou écouteur Tcp), un objet TcpListener.
I-B-2. L'objet NetworkStream( System.Net.Sockets)
L'objet NetworkStream représente le concept de flux de données circulant sur le
réseau. Pour envoyer ou recevoir des données depuis votre objet TcpClient, vous devez
disposer d'un objet NetworkStream. Ce qui semble intuitif ! Une fois cet objet obtenu,
il suffira d'appeler sa méthode de lecture( méthode Read) ou d'écriture(méthode Write).
Pour obtenir un objet NetworkStream associé à votre objet TcpClient, utilisez la
méthode GetStream de votre TcpClient.
NetworkStream monFlux = monClientTcp.GetStream();
|
Fermeture :
I-C. La méthode Write du NetworkStream
La méthode Write permet d'envoyer des données. La syntaxe est la suivante :
byte[] monWriteBuffer;
monFlux.Write(monWriteBuffer, 0,
monWriteBuffer.Length);
|
Le premier paramètre est un tableau d'octets contenant les données à envoyer.
Le deuxième paramètre est l'offset dans ce tableau d'octets, à partir duquel commencent les
données à envoyer. Cela revient à dire que c'est l'indice de début des
données à transmettre. Par exemple, avec un offset = 2, les données transmises seront les
données à partir de monWriteBuffer[2]. Ici nous mettons un offset à 0, c'est le cas le plus
classique.
Le troisième paramètre est la taille des données à transmettre.
Exceptions intéressantes pouvant être déclenchées :
(System.IO).IOException, ObjectDisposedException
Dans le cas où nous devons envoyer une string, qui est un message classique, la démarche
est la suivante :
- Convertir la string en ASCII( l'ASCII n'est plus utilisé, donc la string n'est en
général pas directement en ASCII).
- Obtenir le résultat de cet conversion dans un tableau d'octets( byte[ ])
Une méthode faisant tout ce travail existe déjà. Il s'agit de la méthode GetBytes de
l'attribut statique ASCII( qui est un objet) de
la classe Encoding. Cette dernière fait partie de l'espace de noms System.Encoding .
Autrement dit :
string monMessage;
monWriteBuffer = System.Text.Encoding.ASCII.GetBytes(monMessage.Text);
|
I-D. La méthode Read du NetworkStream
La méthode Read est semblable à la méthode write. Le premier paramètre
est le tableau d'octets qui contiendra les données reçues. Le deuxième paramètre est toujours
l'offset. Le troisième paramètre est le nombre d'octets à lire.
int nbLus = monFlux.Read(monReadBuffer, 0, monReadBuffer.Length);
messageRecu =
System.Text.Encoding.ASCII.GetString(monReadBuffer, 0, nbLus);
Console.WriteLine("Nb d'octet recus: ", nbLus);
|
Exceptions intéressantes pouvant être déclenchées :
(System.IO).IOException, ObjectDisposedExeption, ArgumentOutOfRangeException
I-D-1. Définition : synchrone
La méthode Read est synchrone, c'est-à-dire qu'elle va attendre de
lire le nombre d'octets voulus, pour se terminer : elle est bloquante. Il y a donc une
synchronisation entre celui qui a émis, et le déroulement du programme client, qui va
se bloquer jusqu'à ce que les deux programmes soit synchronisés.
II. La classe TcpListener
La classe TcpListener permet d'obtenir un écouteur de connexion TCP. Les demandes de
connexion peuvent provenir de la classe TcpClient vue ci-dessus, ou de la classe Socket. Ce
qui prouve, une fois de plus, que les classes TcpClient et Socket sont, en réalité, équivalentes,
et peuvent s'utiliser ensembles.
II-A. Création de l'objet TcpListener
private string strIPhote="127.0.0.1";
IPhote = IPAddress.Parse(strIPhote);
monListenTcp = new TcpListener(IPhote, port);
|
Le constructeur demande un objet de la classe IPAddress( System.Net), qu'il est aisé d'obtenir
à partir d'une string, grâce à la méthode statique Parse, de la classe IPAddress. Le numéro
de port est le numéro de port de l'ordinateur hôte.
Exceptions intéressantes pouvant être déclenchées par ce constructeur:
Aucune
II-B. Le démarrage de l'écoute
Le démarrage de l'écoute se fait par l'appel de la méthode start de votre objet TcpListener.
Exceptions intéressantes pouvant être déclenchées :
Uniquement (System.Net.Sockets.).SocketException
Une fois la méthode start appelée, il est nécessaire d'appeler une autre méthode :
AcceptTcpClient, qui est bloquante. On en sort uniquement une fois qu'une connexion a été
établie.
monTcpClient = monListenTcp.AcceptTcpClient();
|
On récupère un objet qui représente notre TcpClient qui vient de se connecter. Cet objet
va être très pratique, car il va nous permettre d'exprimer ce qu'on veut effectuer par
rapport à notre client( recevoir des données, en émettre, etc). Et, de plus, il va s'utiliser
de la même manière que n'importe quel TcpClient : obtention d'un NetWorkStream par GetStream,
appel des méthodes Read quand on veut lire des données envoyées par le client, et Write quand
on veut envoyer des données au client, etc...
II-C. L'arrêt de l'écoute
La fermeture de l'écouteur se fait par un appel de la méthode stop de notre TcpListener.
Exceptions intéressantes pouvant être déclenchées :
Uniquement (System.Net.Sockets.).SocketException
III. Source d'exemple
Voici un source que j'ai écrit pour vous aider à comprendre. Par la même
occasion, vous y trouverez un exemple d'utilisation de thread( cas simple, aucune
synchronisation, mais besoin réel d'un thread).
IV. CONCLUSION
Les classes réseau TcpClient et TcpListener sont intéressantes car elles
donnent le moyen d'accéder aux sockets, tout en gardant un esprit objet. On peut ainsi
réaliser agréablement et joliment une communication TCP. Leur utilisation est assez facile.
. Remerciements


Les sources présentées sur cette page sont libres de droits
et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation
constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ©
. Aucune reproduction,
même partielle, ne peut être faite de ce site et de l'ensemble de son contenu :
textes, documents, images, etc. sans l'autorisation expresse de l'auteur.
Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 €
de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.
Cette page est déposée.