>>>>> Pourquoi avoir utilisé une structure perso (commMessage) pour l'envoi et la réception ?
L'utilisateur de cette classe simplifiée n'a pas à s'inquiéter de ce qu'il envoit et comment il l'envoit. Il envoit juste.
A la réception on reçoit donc un commMessage, on regarde l'ordre (par exemple avec un select case) et on interprete donc le message correctement, l'ordre nous renseignant sur ce qu'on doit faire du message (exemple : est-ce que c'est l'âge du gars, son nom ou bien son prénom ?)
Démo :
Dim cm As ClassComm.CommMessage = _comm.ReadNextMsg
Select Case cm.Order
Case "nom"
Msgbox("La personne connectée s'appelle " & cm.Message & ".")
Case "age"
Msgbox("La personne connectée a " & cm.Message & " ans.")
Case "passion"
Msgbox("La personne connectée est passionnée par " & cm.Message & ".")
End Select
>>>>> Pourquoi ne pas avoir mis en event un message arrivant ?
Parceque les sockets sont multithreads et c'est pas propre du tout : les events sont renvoyés dans un thread à part à cause des callbacks des sockets, donc on ne peut pas agir sur une interface à partir des events renvoyés par la class.
Alors j'ai jugé plus souple de mettre les messages arrivant dans une file d'attente FIFO (first in first out), qui sera par exemple checké par l'utilisateur à l'aide d'un Timer 100ms, ce qui est parfait pour de la comm réseau.
Démo :
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If Not _traitement Then
If _comm.MsgCount > 0 Then
_traitement = True
Dim cm As ClassComm.CommMessage = _comm.ReadNextMsg
'traitement du message ici ou renvoie sur une sub qui traitera
_traitement = False
End If
End If
End Sub
>>>>> C'est quoi idCode dans le commMessage ?
La classe est consciencieuse : quand elle envoit un message, avant de pouvoir en envoyer un nouveau, elle attend d'avoir la confirmation que le message précédent a bien été reçu (bien que le protocole TCP/IP est censé s'en occupé... mais j'ai déjà subit trop de perte en réseau pour des causes inconnues donc avec ça, c'est plus un problème). Chaque message a un idCode unique, et ce code sert d'accusé de réception. Quand la class reçoit un message, elle renvoie l'idCode à l'expéditeur pour dire OK, sinon le dit expéditeur renverra sans cesse le message au bout d'un laps de temps (timeout définit au constructeur) jusqu'à avoir la confirmation que c'est bien reçu.
Pas d'inquiétude, les messages n'arrivent pas en double, le mécanisme est bien géré, tout est vérifié.
Pas d'inquiétude non plus, les nouveaux messages demandés à être envoyé entre un envoi précédent et son propre accusé de réception sont mis en file d'attente pour être envoyé après, donc rien n'est perdu.
Au final on a une class bien aboutie qui gère bien ses comm réseau à la place de l'user.
Bref, ne pas prendre garde à l'idcode, c'est pour info seulement, au cas où on en aurait besoin pour autre chose... sinon pas touche !!
De toute façon c'est une property codée et la valeur de l'IdCode n'est redéfinissable que si elle n'a pas encore été attribuée (valeur 0).
Exemple d'utilisation complet à lire :
Public Class Form1
Private WithEvents Srv As New ClassComm(25000) 'ici on a déjà un serveur en écoute sur le port 25000
Private WithEvents Clt1 As ClassComm
Private WithEvents Clt2 As ClassComm
'en cliquant sur le Button1, on créé le client classComm CLT1 qui va tenter de se connecter au serveur (déjà ouvert juste au dessus)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Clt1 = New ClassComm("localhost", 25000)
End Sub
'ici le serveur reçoit la demande de connexion et l'accepte en créant le client ClassComm CLT2
Private Sub Srv_ConnectionRequestAccepted(ByRef sck As System.Net.Sockets.Socket) Handles Srv.ConnectionRequestAccepted
Clt2 = New ClassComm(sck)
End Sub
'ceci est l'évenement du client ClassComm CLT1 qui confirme que la connexion a bien eu lieu
'a ce stade on a donc une communication prête et ouverte entre CLT1 et CLT2, avec en plus un serveur qui écoute toujours
'normalement c'est fait pour du multiclient donc on devrait pas avoir juste CLT1 et CLT2 mais une collection de client
'et là à ce stade de cette petite appli, vu que ses 2 clients sont pris, on devrait fermer le serveur avec Srv.dispose, mais bref....
Private Sub Clt1_Connected() Handles Clt1.Connected
MsgBox("connecté" )
End Sub
'en cliquand sur le Button2, on fait envoyer un commMessage (ordre + message) par CLT1
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Clt1.Send(InputBox("ordre" ), InputBox("mon message" ))
End Sub
'ici j'ai mis un bouton qui permet de dire si la file d'attente du CLT2 contient des messages
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
MsgBox(Clt2.MsgCount)
End Sub
'et ici un bouton qui lit les messages en attente dans CLT2
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
Dim cm As CommMessage = Clt2.ReadNextMsg
MsgBox(cm.Order & vbCrLf & cm.Message)
'ici il faudrait (exemple) :
'SELECT CASE cm.Order
'CASE "age" : msgbox ("le type a " & cm.Message & " ans" )
'CASE "nom" : msgbox ("le type s'appelle " & cm.Message)
'CASE "profession" : msgbox ("le type travaille dans " & cm.Message)
'END SELECT
End Sub
'Les 2 subs précédentes devraient être dans un Timer avec un test sur MsgCount
'ici un exemple de l'event ProblemDetected chez CLT1
Private Sub Clt1_ProblemDetected(ByVal source As ClassComm.ErrorType) Handles Clt1.ProblemDetected
Select Case source
Case ErrorType.connection_failed : MsgBox("échec connexion" )
Case ErrorType.seems_disconnected : MsgBox("semble déconnecté" )
End Select
Clt1.Dispose()
Clt1 = Nothing
End Sub
End Class