Le premier site francophone dédié au développement Pocket PC


Utilisation du contrôle Winsock (partie 2)
 


Partie 1
Partie 2

Le client se connecte à son serveur

Pour se connecter au serveur, le client doit en faire la demande. Pour cela, il doit au préalable paramétrer sont contrôle WinSock en vue de cette connexion :

WinSock1.RemoteHost = WinSock1.LocalHostName
WinSock1.RemotePort = 8000

Si vous ne savez plus pourquoi on affecte la valeur 8000 à la propriété RemotePort je vous invite à consulter la première partie de cet article.

Puis demander une connexion :

On Error Resume Next
 Call WinSock1.Connect
 If Err.Number <> 0 Then MsgBox "Connexion impossible", vbInformation, "WinSock"
On Error GoTo 0


Il est préférable de gérer l'erreur qui pourrait se produire en cas de mauvais paramètres ou de serveur non démarré, c'est pour cela que la méthode Connect est encapsulée dans un On Error.

Lorsque la méthode Connect est invoquée, et que la connexion est acceptée par le serveur visé, un événement Connect est généré. C'est uniquement à partir de ce moment que vous pouvez considérer que le contrôle WinSock client est en liaison avec le contrôle WinSock serveur. Dans notre programme d'exemple nous profitons de cet événement pour invalider le bouton de connexion et autoriser les boutons d'envoi et de déconnexion :

Private Sub WinSock1_Connect()
BOU_Connecter.Enabled = False BOU_Deconnecter.Enabled = True BOU_Envoyer.Enabled = True
End Sub

Le client envoie des infos au serveur

Pour envoyer des infos au serveur, le client utilise exactement la même méthode que celle que le serveur utilise pour répondre, la méthode SendData. Dans notre exemple, lorsqu'on clique sur le bouton "Envoyer" ce code est invoqué :

Private Sub BOU_Envoyer_Click()
 Dim wBuffer As String
 wBuffer = InputBox("Question à destination du serveur.", "Question")
 If wBuffer <> "" Then Call WinSock1.SendData(wBuffer)
End Sub

La méthode SendData génère 2 événements, tout d'abord un événement SendProgress qui permet de connaitre le nombre d'octets envoyés et le nombre d'octets restant à envoyer. Le contrôle WinSock envoie les données par paquets de 8Ko (8196 octets), donc si vos données font moins de 8Ko vous n'aurez qu'un seul événement SendProgress généré. Une fois l'envoi complètement effectué, c'est l'événement SendComplete qui est généré. Ces événements sont très utiles si vous envoyez de grosses quantités de données (indication de la progression) et pour afficher la fin d'un envoi. Dans notre exemple, nous pourions très bien invalider le bouton d'envoi lors de l'appel à la méthode SendData et le rendre de nouveau actif à la réception de l'événement SendComplete.

Le bug qui tue

Le contrôle WinSock est très puissant et offre de grands services, mais comme rien n'est simple dans ce monde, il est porteur d'un gros bug. En effet, vous allez très rapidement le remarquer, lorsqu'un contrôle WinSock reçoit des données, il génère 1 événement DataArrival pour le premier caractère reçu, puis un autre DataArrival pour le reste. Si vous devez recevoir "BONJOUR", vous allez d'abord recevoir "B" puis "ONJOUR". Pas cool !

Il existe un moyen simple de controurner ce problème. Lorsque vous envoyez vos données, faites les terminer par un caracètre spécial de fin (postambule). Perso j'utilise le caractère dont le code ascii est 1 et que l'on obtient avec la fonction Chr(1). Il ne faut surtout pas utiliser Chr(0) car il sera ignoré. Lorsque vous recevez un événement DataArrival, vous lisez le contenu du buffer que vous placez immédiatement à la fin d'une variable de travail de type String, ensuite vous vérifiez que cette chaine contient le caractère spécial de fin. Si ce n'est pas le cas, on laisse tomber en attendant le prochain DataArrival, si le caractère de fin est présent, il faut traiter la chaine composée du début de la variable de travail jusqu'au caractère de séparation et laisser dans cette même variable le reste (qui est en attente de reconstruction). Un peu de code ça sera plus clair :

Déclaration de la variable de travail (dans la section déclaration de la fenêtre par exemple) :

Public BufferWinSock As String

Code dans l'événement DataArrival

Private Sub WinSock1_DataArrival
 
Rem On récupère les données arrivées Dim wBuffer As String Call WinSock1.GetData(wBuffer)
Rem On ajoute ces données toutes fraiches à la variable de travail BufferWinSock = BufferWinSock & wBuffer
Rem On vérifie que le caractère de fin de trame est présent Dim k As Integer k = Instr(BufferWinSock, Chr(1)) If k>0 Then Rem Le caractère est présent, on traite le message Rem Et on met à jour la variable de travail Call TraiterMessageWinSock(Mid(BufferWinSock, 1, k)) BufferWinSock = Mid(BufferWinSock, k+1) End If
End Sub

Il ne reste plus qu'à créer une procédure qui traite le message :

Public Sub TraiterMessageWinSock(Byval wMessage As String)

Rem On traite ici le message complet reçu par le WinSock Rem Attention, le message se termine par le caractère de fin Chr(1)
 Rem Ici le code de traitement .....
End Sub

A partir du moment où on utilise ce système, il faut que le client et le serveur soient en phase et utilise le même caractère de fin lors de leurs envois respectifs.

Le sources de cet articles

Comme nous avons effectué quelques changements aussi dans le serveur je vous propose de télécharger la dernière version.

Sources du serveur (version 2)
Sources du client

Attention de bien avoir lancé le serveur avant de demander une connexion depuis le client, sinon erreur...

Il y a d'autres événements liés au contrôle WinSock, je vous invite a tester vous même leurs réactions et leur utilité comme exercice de cet article.

Stéphane Sibué

   
 
 
Copyright 2001-2004 - Tous droits réservés
 

iPAQ est un produit de COMPAQ.
Visual Tools est un produit de Microsoft Corporation.
Toutes les autres marques et produits présents dans ces pages sont la propriété exclusive de leurs sociétés respectives.