Problème avec stringbuilder et socket

Résolu
cs_Kite37 Messages postés 242 Date d'inscription lundi 6 mars 2006 Statut Membre Dernière intervention 17 janvier 2018 - 15 avril 2008 à 22:44
cs_Megafan Messages postés 389 Date d'inscription dimanche 7 avril 2002 Statut Membre Dernière intervention 23 septembre 2016 - 17 avril 2008 à 18:56
Bonjour !

Dans le cadre d'une mise en mode online d'un de mes logiciels, je me suis intéressé à l'utilisation en mode asynchrone des sockets.
Cependant, lors de la récupération des données (qui sont censée être stockées dans un stringbuilder jusqu'à lecture de la balise "<end>"), j'ai un problème assez génant.

Normalement, lorsqu'un message reçu ne contient pas "<end>", il est stocké dans le stringbuilder, et ainsi de suite jusqu'à ce qu'un message contenant "<end>" soit reçu, auquel cas le contenu du stringbuilder est affiché a l'écran dans son intégralité.

Mais voilà, malgré le code ci-dessous qui devrait théoriquement marcher, seul le premier message stocké dans le stringbuilder est affiché a l'écran au lieu de l'intégralité du contenu qu'il est censé recevoir..

Je ne sais pas si je suis très clair dans mes explications, veuillez m'en excuser .

Ci-dessou le code de la méthode asynchrone de réception de données et d'affichage. Il n'est pas commenté, mais je ne pense pas qu'il soit dur a comprendre.

Private Sub receiveCallBack(ByVal obj As IAsyncResult)
        Dim handler As Socket = CType(obj.AsyncState, Socket)

        Dim bytesInc As Integer = handler.EndReceive(obj)
        Dim data As String = String.Empty

        If bytesInc > 0 Then

            data = Encoding.UTF8.GetString(buffer)

            If data.IndexOf("<end>") > -1 Then
                data = sb.ToString() & Mid(data, 1, data.IndexOf("<end>"))

                sb.Remove(0, sb.Length)

                Me.txtInc.Text = data

                handler.BeginReceive(buffer, 0, bufferSize, 0, New AsyncCallback(AddressOf receiveCallBack), handler)
            Else
                sb.Append(data)
           
                handler.BeginReceive(buffer, 0, bufferSize, 0, New AsyncCallback(AddressOf receiveCallBack), handler)
            End If

        End If
      
    End Sub

J'espère que quelqu'un pourra me dépanner, merci d'avance.

Cordialement, Kite

9 réponses

cs_Megafan Messages postés 389 Date d'inscription dimanche 7 avril 2002 Statut Membre Dernière intervention 23 septembre 2016 2
16 avril 2008 à 15:48
Salut,
1 - Si tu penses que c'est l'ajout au string builder qui pose un probléme, passe par une chaine que tu concatenes à chaque CallBack....

2 -Pour moi l'interet du StateObject est de gérer ton traitement asynchrnone dans un seul objet
genre exemple d'une classe SO que j'utilise...

Public

Class HTTPStateObject

Public
Const BufferSize
As
Integer = 8192

Public HTTPSocket
As Socket =
Nothing
Public HTTPAsyncBuffer(BufferSize)
As
Byte
Public HTTPBuffer()
As
Byte = {}

Public EndOfHeader
As
Integer = -1

Public ContentLength
As
Long = -1
End

Class

donc tout se qui va se rapporter au traitement
Comme tu peux le constater j'utilise un buffer complet (HTTPBuffer) que je remplis à chaque evenement ReadCallBack en 'concatenant' HTTPAsyncBuffer. Tu peux y ajouter l'IP du Client ou tout un tas de choses...

@+ Megafan
3
cs_Kite37 Messages postés 242 Date d'inscription lundi 6 mars 2006 Statut Membre Dernière intervention 17 janvier 2018
17 avril 2008 à 12:33
J'ai modifié mon code, en réutilisant le classe stateObject (ici correspond à l'objet reader) et ça marche.

Voici le code :

 Private Sub receiveCallBack(ByVal obj As IAsyncResult)
        Dim state As clsRemoteReader = CType(obj.AsyncState, clsRemoteReader)
        Dim bytesInc As Integer = state.mainSocket.EndReceive(obj)

        Dim data As String = String.Empty
        Dim index As Integer

        If bytesInc > 0 Then

            data = Encoding.UTF8.GetString(state.buffer, 0, bytesInc)

            Array.Clear(state.buffer, 0, state.buffer.Length)

            index = data.IndexOf("<end>")

            If index > -1 Then
                data = state.sb.ToString() + Mid(data, 1, index)

                state.sb.Remove(0, state.sb.Length)

                state.sb.Append(Mid(data, index, data.Length - 1), 0, Mid(data, index, data.Length - 1).Length)

                Me.txtInc.Text = data

                state.mainSocket.BeginReceive(state.buffer, 0, state.bufferSize, 0, New AsyncCallback(AddressOf receiveCallBack), state)
            Else
                state.sb.Append(data, 0, bytesInc)

                state.mainSocket.BeginReceive(state.buffer, 0, state.bufferSize, 0, New AsyncCallback(AddressOf receiveCallBack), state)
            End If

        End If
     
    End Sub
3
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 71
16 avril 2008 à 07:17
déclaré où, ton stringBuilder ?

je vois pas non plus ou est déclaré et affecté 'buffer'
0
cs_Kite37 Messages postés 242 Date d'inscription lundi 6 mars 2006 Statut Membre Dernière intervention 17 janvier 2018
16 avril 2008 à 09:53
Mon stringbuilder et mon buffer son des variables private normalement visibles dans tout le module.
0

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

Posez votre question
cs_Megafan Messages postés 389 Date d'inscription dimanche 7 avril 2002 Statut Membre Dernière intervention 23 septembre 2016 2
16 avril 2008 à 10:59
Salut,

Effectivement coté code je vois rien d'anormal au premier abord, par contre quand tu dis

seul le premier message stocké dans le stringbuilder est affiché a l'écran au lieu de l'intégralité du contenu qu'il est censé recevoir..

A tu vérifié :

- Tu rentre 1 fois dans le callback sans avoir le <end> dans ton buffer ?
---> rentre tu a nouveau dans ton callback ? et tu  ne recois plus rien
- Tu peux tester si bytyeInc=0 , l'application distante n'a t'elle pas fermée le socket ?
---> quelle est la taille de ton buffer ?

- Personnelement en asynchrone je travaille toujours avec un StateObject (voir  msdn)
dans lequel je gére mon socket, mon buffer Asynchrone et mon buffer complet (ton sb)

Donne des nouvelles

@+ Megafan
0
cs_Kite37 Messages postés 242 Date d'inscription lundi 6 mars 2006 Statut Membre Dernière intervention 17 janvier 2018
16 avril 2008 à 11:21
Oui j'ai fait des test avec tout ce que tu me dis : je reçoit bien des données mais c'est lors de l'ajout au stringbuilder qu'il y a un problème.

Même chose en utilisant le stateOject de MSDN (c'est d'ailleurs pour cela que j'ai essayer de tout séparer).

Je pense que je vais reprendre mon code de zéro, il doit y avoir quelques chose qui m'a échappé :s

Cordialement, KiTe
0
cs_Kite37 Messages postés 242 Date d'inscription lundi 6 mars 2006 Statut Membre Dernière intervention 17 janvier 2018
16 avril 2008 à 13:05
En fait il y des choses quime dérange dans la version de MSDN, peut être pourrez vous m'expliquer :

 Private Sub acceptCallBack(ByVal obj As IAsyncResult)
        Dim listener As Socket = CType(obj.AsyncState, Socket)
        Dim handler as socket = listener.EndAccept(obj)

        Dim State as new StateObject()

         State.workSocket = handler

       handler.BeginReceive(buffer, 0, bufferSize, 0, New AsyncCallback(AddressOf receiveCallBack), state)
    End Sub

Quelle est l'utilité de passer par un Socket intermédiaire (handler) alors qu'il serait plus simple de faire :

 Private Sub acceptCallBack(ByVal obj As IAsyncResult)
        Dim conSock As Socket = CType(obj.AsyncState, Socket)
   
        Dim State as new StateObject()
        State.workSocket = conSock.endAccept(obj)

        State.workSocket .BeginReceive(buffer, 0, bufferSize, 0, New AsyncCallback(AddressOf receiveCallBack), State)
    End Sub

Car au final il n'y a pas vraiment de différence, et une économie mémoire (handler n'est pas utilisé) pour au final passer le meme stateObject et donc le meme socket en paramètre ..

Cordialement Kite
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 71
16 avril 2008 à 13:26
ca ne change pas grand chose...
j'ignore l'impact sur l'execution (minime, j'imagine)
0
cs_Megafan Messages postés 389 Date d'inscription dimanche 7 avril 2002 Statut Membre Dernière intervention 23 septembre 2016 2
17 avril 2008 à 18:56
Salut,
Bien.
Content d'avoir pu t'aider.
@+
Megafan
0
Rejoignez-nous