IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Découverte des sockets


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut Découverte des sockets
    Hello,

    Je découvre actuellement les sockets et leur utilisation.

    J'ai suivi de l'exemple simple client/serveur où le client demande l'heure au serveur qui la lui renvoie.

    Cela fonctionne fort bien (à ou deux détails près dont la correction fut aisée).

    A partir de là, je me suis dit que j'allais testé de conditionné la réponse du serveur en fonction d'un paramètre envoyé par le client.

    J'ai donc modifié leur méthode TraitementConnexion du client comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        Private Sub TraitementConnexion(SocketReception As Socket, prm As String)
            Console.WriteLine("Connecté, réception de " & prm & ": ")
            Dim bytes(255) As Byte 'création du tableau de réception
            Try
                SocketReception.Send(System.Text.Encoding.ASCII.GetBytes(prm)) 'envoi de la demande
                SocketReception.Receive(bytes) 'réception de l'information
                Console.WriteLine(System.Text.Encoding.ASCII.GetString(bytes)) 'affichage de la date ou de l'heure
            Catch ex As Exception
                Console.WriteLine("Erreur lors de la réception des données : " & ex.ToString)
            End Try
        End Sub
    Et la méthode TraitementConnexion du serveur comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
        Private Sub TraitementConnexion(socketEnvoi As Socket)
            Console.WriteLine("Socket client connecté")
            Try
                Dim bytes(255) As Byte
     
                socketEnvoi.Receive(bytes)
     
                Dim demande As String = System.Text.Encoding.ASCII.GetString(bytes)
                Console.WriteLine("demande reçue : " & demande)
     
     
                If demande = "heure" Then
                    Console.WriteLine("envoi de l'heure")
                    socketEnvoi.Send(System.Text.Encoding.ASCII.GetBytes(Now.ToLongTimeString))
                Else
                    Console.WriteLine("envoie de la date")
                    socketEnvoi.Send(System.Text.Encoding.ASCII.GetBytes(Now.Date.ToShortDateString))
                End If
     
                'Dim heure As Byte() = System.Text.Encoding.ASCII.GetBytes(Now.ToLongTimeString) 'convertit l'heure en bytes
     
                'Dim envoi As Integer = socketEnvoi.Send(heure) 'envoie l'heure au client
                ' Console.WriteLine(envoi & " bytes envoyés au client")
            Catch ex As Exception
                Console.WriteLine("Erreur lors de l'envoi du message au socket." & ex.ToString)
            End Try
        End Sub
    Pour finir, sur le client, je fais ceci pour effectuer les demandes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
       Dim port As Integer = 8080
        Dim ip As String = "127.0.0.1"
     
        Sub Main()
            Dim monSocketClient As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
     
            Dim monEP As IPEndPoint = New IPEndPoint(IPAddress.Parse(ip), port)
     
            Console.WriteLine("Socket client initialisé")
     
            Try
                Console.WriteLine("Connexion au serveur...")
                monSocketClient.Connect(monEP)
                TraitementConnexion(monSocketClient, "heure")
                TraitementConnexion(monSocketClient, "date")
            Catch ex As Exception
                Console.WriteLine("Erreur lors de la tentative de connexion : " & ex.ToString)
            End Try
     
            If monSocketClient.Connected Then
                monSocketClient.Close()
            End If
     
            Console.ReadLine()
        End Sub
    Evidemment (si je ne serais pas là), cela ne fonctionne pas...

    Lors du premier appel, le serveur renvoie la date au lieu de l'heure et le deuxième appel semble ne pas recevoir de réponse...
    La fenêtre de console du client affiche désespérément "Connecté, réception de date : ".
    La fenêtre de console du serveur affiche qu'il reçoit la demande "heure" mais envoie quand même la date et semble ne pas recevoir la deuxième demande.

    J'ai donc deux problèmes.

    Pourquoi le serveur interprète-t-il mal la demande du client et pourquoi la 2e demande du client ne semble pas parvenir au serveur ?

    J'imagine que ça doit être quelque chose de plus ou moins trivial mais vu que je débute avec ces choses que sont les sockets, je tourne un peu en rond.

    Merci d'avance.

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    pour le fait que tu aies la date au lieu de l'heure en premier, c'est que demande ne vaut pas "heure"
    donc ca passe dans le else
    (après pourquoi c'est une autre question, avec un point d'arrêt tu verrais le contenu)
    tu aurais mis elseif = "date" au lieu de else tu aurais remarqué ca (enfin si je me trompe pas)

    pour le fait que tu n'as qu'une réponse c'est parce qu'une fois la méthode receive appelée et débloquée par une réception il faut réappeler receive pour recevoir autre chose, et ainsi de suite

    la méthode receive est bloquante, il y a beginreceive qui est asynchrone
    il y a donc 2 implémentations possibles une fois les petits tests comme tu le fais passés
    soit un thread qui utilise les méthodes synchrones, soit l'utilisation des méthodes asynchrones
    (beginaccept et autre aussi, d'ailleurs il faut aussi de nouveau appeler accept/beginaccept après la connexion de chaque client pour pouvoir en accepter un autre)


    sinon le socket en tcp/ip te garantie juste que l'ordre d'envoie sera respecté, par contre pour le nombre de blocs c'est tout autre chose
    une trame (octets transférés) peut être découpée en plusieurs, et plusieurs petites trames peuvent être collées

    aussi quand on utilise le tcp/ip on se créé une norme de transmission permettant de passer outre ces problèmes
    l'une des plus connues est l'utilisation d'un caractère(octet) de début de trame et d'un de fin de trame
    comme ca on s'occupe de recoller tout ce qui arrive, et quand on repère un morceau ayant un début et une fin on le traite
    on a donc en général une classe de transmission et une classe de traitement
    il y a aussi la méthode qui consiste en plus à passer une taille de transmission, le receveur ayant lu cette données en début de trame peut alors attendre x octets de manière sûre
    le protocole http qui utilise le tcp/ip utilise d'ailleurs le content size dans le header


    sinon pour s'affranchir de tout ca il y a des surcouches, comme wcf, ici on appelle juste une méthode d'une interface côté client et cette méthode est exécutée côté serveur
    les paramètres et les retours de fonctions sont sérialisés et découpés par wcf sans qu'on se pose de question permettant de faire transiter des instances ...
    comme tout surcouche elle coute peut etre un peu en perf et/ou en souplesse
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Avant tout, merci pour ta réponse.
    Citation Envoyé par Pol63 Voir le message
    pour le fait que tu aies la date au lieu de l'heure en premier, c'est que demande ne vaut pas "heure"
    donc ca passe dans le else
    (après pourquoi c'est une autre question, avec un point d'arrêt tu verrais le contenu)
    tu aurais mis elseif = "date" au lieu de else tu aurais remarqué ca (enfin si je me trompe pas)
    J'avais mis un breakpoint et la valeur de la variable demande de la méthode TraitementConnexion du serveur contenait bien "heure". Maintenant, je dis pas qu'il y a pas un truc qui fait que deux strings de contenus apparemment identiques soient en fait différent. J'ai cherché mais pas trouvé.

    Citation Envoyé par Pol63 Voir le message
    pour le fait que tu n'as qu'une réponse c'est parce qu'une fois la méthode receive appelée et débloquée par une réception il faut réappeler receive pour recevoir autre chose, et ainsi de suite
    Si tu regardes mon code, le client appelle bien 2 fois la méthode TraitementConnexion. Et dans cette méthode, il y a bien l'instruction Receive donc elle est bien appelée 2 fois.
    Citation Envoyé par Pol63 Voir le message
    la méthode receive est bloquante, il y a beginreceive qui est asynchrone
    il y a donc 2 implémentations possibles une fois les petits tests comme tu le fais passés
    soit un thread qui utilise les méthodes synchrones, soit l'utilisation des méthodes asynchrones
    (beginaccept et autre aussi, d'ailleurs il faut aussi de nouveau appeler accept/beginaccept après la connexion de chaque client pour pouvoir en accepter un autre)
    Oui oui, j'avais bien vu que c'était synchrone et qu'il y a moyen de faire du traitement asynchrone histoire de ne pas freezer l'application mais chaque chose en son temps. Avant de courir, j'aimerais savoir marcher d'abord^^.
    Citation Envoyé par Pol63 Voir le message

    sinon le socket en tcp/ip te garantie juste que l'ordre d'envoie sera respecté, par contre pour le nombre de blocs c'est tout autre chose
    une trame (octets transférés) peut être découpée en plusieurs, et plusieurs petites trames peuvent être collées

    aussi quand on utilise le tcp/ip on se créé une norme de transmission permettant de passer outre ces problèmes
    l'une des plus connues est l'utilisation d'un caractère(octet) de début de trame et d'un de fin de trame
    comme ca on s'occupe de recoller tout ce qui arrive, et quand on repère un morceau ayant un début et une fin on le traite
    on a donc en général une classe de transmission et une classe de traitement
    il y a aussi la méthode qui consiste en plus à passer une taille de transmission, le receveur ayant lu cette données en début de trame peut alors attendre x octets de manière sûre
    le protocole http qui utilise le tcp/ip utilise d'ailleurs le content size dans le header
    C'est une information super importante !! Vu le peu de succès que j'avais avec les sockets "purs et dures", j'ai testé les classes TcpClient et TcpListener en utilisant les stream donc. Sans cette information, je n'aurais pas compris pourquoi mon While not reader.EndOfStream (où reader est de type IO.StreamReader) ne sortait jamais de la boucle. J'ai donc ajouté des données indiquant la fin de la transmission pour savoir quand sortir de la boucle et ça marche nickel.
    Citation Envoyé par Pol63 Voir le message

    sinon pour s'affranchir de tout ca il y a des surcouches, comme wcf, ici on appelle juste une méthode d'une interface côté client et cette méthode est exécutée côté serveur
    les paramètres et les retours de fonctions sont sérialisés et découpés par wcf sans qu'on se pose de question permettant de faire transiter des instances ...
    comme tout surcouche elle coute peut etre un peu en perf et/ou en souplesse
    WCF est la prochaine étape de mon exploration. C'est l'objectif que je me suis fixé mais j'aime bien comprendre comment les choses fonctionnent (au moins un minimum) avant de les utiliser. Alors j'ai donc testé les sockets pour me faire une idée.

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    Citation Envoyé par Kropernic Voir le message
    J'avais mis un breakpoint et la valeur de la variable demande de la méthode TraitementConnexion du serveur contenait bien "heure". Maintenant, je dis pas qu'il y a pas un truc qui fait que deux strings de contenus apparemment identiques soient en fait différent. J'ai cherché mais pas trouvé.
    si tu as mis un breakpoint tu as du voir de tes propres yeux que ca ne rentrait pas dans le if alors
    et il aurait fallu faire un espion express de la condition du if pour voir si true ou false



    Citation Envoyé par Kropernic Voir le message
    Si tu regardes mon code, le client appelle bien 2 fois la méthode TraitementConnexion. Et dans cette méthode, il y a bien l'instruction Receive donc elle est bien appelée 2 fois.
    je parlais du serveur
    il faut .receive, puis .send puis rien, il faut un nouveau receive
    tcpclient et tcplistener sont légèrement différents, mais il s'appuie tous les 2 sur la classe de plus bas niveau et qui fait encore plus peur net.sockets.socket
    donc le fonctionnement est le même
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Lol oui j'avais bien vu que ça passait dans le else mais j'ai pas compris pourquoi car en mettant la souris sur la variable et en regardant sont contenu, il était bien noté "heure" ^^.

    Sinon, je maintenant que j'ai une idée, je suis passé à wcf. De ce que j'en ai vu jusqu'ici, ça fonctionne comme un webservice... Pas encore trouver le moyen pour que le server disent un truc au client sans que le client ne lui demande qqch...

    Je continue à fouiller

  6. #6
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    avec les string il faut faire gaffe, certains caractères ne s'affichent pas
    d'où tester le test du if dans l'espion express

    wcf est en effet un webservice
    pour que le serveur puisse dialoguer avec le client comme si le client était un serveur il faut un service de callback wcf
    quand le client se connecte il précise qu'il a un service en retour, et le client le garde dans une variable pour pouvoir faire des appels dessus
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

Discussions similaires

  1. Chat basé sur des sockets php5
    Par javhost dans le forum Développement
    Réponses: 1
    Dernier message: 12/07/2005, 16h21
  2. Réponses: 2
    Dernier message: 12/10/2004, 13h04
  3. connection/deconnection des sockets
    Par yotasse dans le forum Développement
    Réponses: 3
    Dernier message: 17/02/2004, 12h08
  4. probleme de gestion de clients avec des sockets....
    Par ludvo dans le forum Réseau
    Réponses: 6
    Dernier message: 25/09/2003, 12h37
  5. utilisation des sockets sous windows
    Par Tupac dans le forum Réseau
    Réponses: 2
    Dernier message: 21/12/2002, 18h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo