Comment extraire les variables d'un bloc (réponse de serveur) contenant plusieur

Résolu
Caacrino Messages postés 8 Date d'inscription mardi 10 mai 2011 Statut Membre Dernière intervention 18 août 2011 - 10 mai 2011 à 01:38
Caacrino Messages postés 8 Date d'inscription mardi 10 mai 2011 Statut Membre Dernière intervention 18 août 2011 - 10 mai 2011 à 17:57
Bonjour,

Depuis quelques jours je cherche à exploiter une réponse de requête serveur qui contient plusieurs types de variables différents.

Grosso modo j'envoie une requête à un serveur, et en retour le serveur me renvoie une réponse sous la forme du bloc suivant:

<string><long><string><long>

Comment puis-je extraire chaque variable proprement de ce bloc ? Peut-on transformer ce bloc en un tableau ?

Merci d'avance pour votre aide !

7 réponses

foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
10 mai 2011 à 13:19
Ok, dans ce cas vous pouvez utiliser un MemoryStream pour stoquer votre buffer et un BinaryReader pour lire le stream en fonction de la structure de la trame.

Voici un exemple
Imports System.IO

Dim ReceiveBuffer As Byte()
ReceiveBuffer = UdpSender.Receive(New Net.IPEndPoint(Net.IPAddress.Any, 0))

Dim byte1 As Byte
Dim byte2 As Byte
Dim string1 As String
Dim byte3 As Byte
Dim long1 As Long
Dim string2 As String
Dim byte4 As Byte
Dim long2 As Long

'Création d'un MemoryStream à partir du buffer
'et d'un BinaryReader pour lire les données
Using ms As New MemoryStream(ReceiveBuffer), _
      reader As New BinaryReader(ms)

     'Lecture des valeurs dans l'ordre de la trame
     byte1 = reader.ReadByte()
     byte2 = reader.ReadByte()
     string1 = reader.ReadString()
     byte3 = reader.ReadByte()
     long1 = reader.ReadInt64()
     string2 = reader.ReadString()
     byte4 = reader.ReadByte()
     long2 = reader.ReadInt64()

End Using


Il suffit donc de lire le bon type dans l'ordre dans lequel les données sont stockées dans votre trame.

Dans mon exemple, j'ai simplement récupéré les données de votre trame dans des variables avec une trame du type:

<string><long><string><long>

Après rien ne vous empèche de créer une structure ou de stocker les valeurs dans une table.

Je conseil aussi de controler la taille du buffer avant de commencer l'extraction pour ne pas générer d'erreur lors de la lecture.
3
foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
10 mai 2011 à 17:24
C'est vrai que le cas des string est particulier, j'aurai du le préciser.

Dixit MSDN, la fonction ReadString du BinaryReader fait ceci
Lit une chaîne à partir du flux actuel. La chaîne est préfixée à l'aide de la longueur, codée comme un entier à raison de sept bits à la fois


Donc, il faudrait que votre serveur fournisse la longueur du pseudo en préfixe dans la trame (dans les 4 octets juste avant le pseudo), ce qui n'est pas le cas à priori.

Donc vous n'avez que deux possibilités :

1) Si vous ne connaissez pas la longueur de la chaine à lire

Dans ce cas, il faut utiliser votre méthode qui lit chaque caractère et s'arrète à un caractère de fin (Chr(10) dans votre cas).

2) Si vous connaissez la longueur de la chaine

Vous pouvez faire
Dim userpseudo As String = reader.ReadChars(nbDeCaracteres)
3
foliv57 Messages postés 420 Date d'inscription vendredi 17 novembre 2006 Statut Membre Dernière intervention 15 juillet 2014 9
10 mai 2011 à 08:45
Bonjour,

Il va falloir être un peut plus précis.

Sous quelle forme la réponse du serveur est-elle récupérée ? (Tableau d'octets, fichier xml, fichier text ...)
0
Caacrino Messages postés 8 Date d'inscription mardi 10 mai 2011 Statut Membre Dernière intervention 18 août 2011
10 mai 2011 à 11:43
Oui effectivement Foliv57, si j'oublie le principal on ne va pas aller très loin, toutes mes excuses :p

J'utilise un socket udp (sous vb.net 2008) pour demander les infos au serveur. La réponse du serveur est sous forme d'octets, la taille du tableau/paquet étant variable comme déclaré ci-dessous pour l'exemple.

Dim ReceiveBuffer As Byte()
ReceiveBuffer = UdpSender.Receive(New Net.IPEndPoint(Net.IPAddress.Any, 0))


Je cherche donc à décomposer le paquet reçu dans mon tableau d'octets dénommé "ReceiveBuffer" pour extraire les différents types de variables stockées dedans. Les différents types de variables à récupérer sont: Byte, Short, Long, Float, et String (et pas forcément stockés dans l'ordre)...

Merci d'avance pour vos lumières ;)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Caacrino Messages postés 8 Date d'inscription mardi 10 mai 2011 Statut Membre Dernière intervention 18 août 2011
10 mai 2011 à 16:39
Fantastique, exactement ce que je cherchais désespérement !
Je valide de suite, une réponse claire et concrète, je ne pouvais rêver mieux, merci beaucoup Foliv57

Cela dit, j'ai encore une toute petite question car je rencontre un léger souci avec reader.readstring sur la structure suivante:

Structure du paquet sur lequel je travaille:
(int32)(byte)(byte)(byte)(string)(int32)(float32)

Mon code qui pose problème:
            Dim Entete As Integer = reader.ReadInt32()
            Dim TypeRequest As Byte = reader.ReadSByte()
            Dim NumUsers As Byte = reader.ReadSByte()
            Dim userid As Byte=reader.readbyte()
            Dim userpseudo As String = reader.readstring()
            Dim userflag As Integer=reader.readint32()
            Dim usertime As Long=reader.readsingle()


Le reader.readstring() stocke dans ma variable userpseudo tout le reste du paquet, du coup userflag et usertime ne peuvent plus avoir de valeur et ça plante le programme. Cependant j'ai remarqué qu'à la fin de chaque pseudo, il y avait un caractère spécial chr(10) (retour chariot sauf erreur), alors j'ai résolu le bogue de la façon suivante :

            Dim Entete As Integer = reader.ReadInt32()
            Dim TypeRequest As Byte = reader.ReadSByte()
            Dim NumUsers As Byte = reader.ReadSByte()
            Dim userid As Byte=reader.readbyte()

            Dim userpseudo as string = ""
                Dim trouve As Boolean = False
                Dim c As Char
                While trouve = False
                    c = reader.ReadChar()
                    If c <> Chr(0) Then
                        userPseudo = userPseudo + c
                    Else
                        trouve = True
                    End If
                End While

            Dim userflag As Integer=reader.readint32()
            Dim usertime As Long=reader.readsingle()



A tout hasard, y'a-t-il une meilleure façon de faire que mon bidouillage ?
0
Caacrino Messages postés 8 Date d'inscription mardi 10 mai 2011 Statut Membre Dernière intervention 18 août 2011
10 mai 2011 à 16:53
Je viens de m'apercevoir d'une erreur d'étourderie dans mon post précédent, malheureusement je ne parviens pas à éditer/corriger le post en question donc je corrige ici pour éviter la confusion: Le caractère spécial à la fin des pseudos est bien chr(0) et non pas chr(10) comme j'ai pu l'écrire dans mon explication...
0
Caacrino Messages postés 8 Date d'inscription mardi 10 mai 2011 Statut Membre Dernière intervention 18 août 2011
10 mai 2011 à 17:57
Malheureusement le serveur ne me retourne aucune longueur de chaîne, et c'est surement la raison pour laquelle il clôture chaque string par un chr(0), je conserverais donc le dernier script tel quel, celui-ci répondant déjà parfaitement à mes besoins.

En tout cas, je vous suis vraiment reconnaissant pour votre aide, vous m'avez résolu en quelques minutes un problème qui m'embêtait depuis 2 jours, j'ai pourtant googlé en long et en large, mais je ne devais pas utiliser les bons mots clés faute de savoir exactement ce que je devais chercher... Si on avait plus de gens comme vous sur le net, on éviterait bien des galères en matière de compréhension et la plupart des forums deviendraient plus qu'intéressants et productifs.

Merci encore, et bonne continuation !
0
Rejoignez-nous