[.NET 2.0]NetworkStream.BeginWrite => dataavailable = fal

dnx
[.NET 2.0]NetworkStream.BeginWrite => dataavailable = fal

Bonjour,

je suis coincé sur un problème depuis quelques jours...
le problème est le suivant,

j'utilise un TCPClient pour me connecter à un port particulier
jusque là, la connexion se fait bien, je reçois une belle réponse du serveur

directement (networkstream et tcpclient sont toujours ouverts!) j'écris un autre message (commande), le serveur me réponds toujours.
et à la 3e écriture, il me plante... la propriété "DataAvailable" du networkstream est à false... impossible d'avoir une réponse du serveur !

je ne comprends pas...

quelqu'un peut m'aider?

Merci d'avance

 
 Public Function Connect() As Boolean
 
            Dim bytes As Int32
            Dim responseData As String
 
            Try
                Me._client = New TcpClient(Me._server, Me._port)
                ' Get a client stream for reading and writing.
                Me._client.NoDelay = True
                Me._stream = Me._client.GetStream()
                Me._buffer = New Byte(Me._client.ReceiveBufferSize) {}
                bytes = Me._stream.Read(Me._buffer, 0, Me._buffer.Length)
                responseData = System.Text.Encoding.ASCII.GetString(Me._buffer, 0, bytes)
                If responseData.Trim.ToLower.Contains("playbox") Then
                    Return True
                Else
                    Return False
                End If
            Catch ex As Exception
                Return False
            End Try
            Return True
        End Function
 
        Public Sub Disconnect()
            If Me._client IsNot Nothing Then
                Me._client.Close()
            End If
            If Me._stream IsNot Nothing Then
                Me._stream.Close()
            End If
        End Sub
 
     Private Function SendCommand(ByVal Message As String) As String
 
            'Dim data As Byte()
            'data = System.Text.Encoding.ASCII.GetBytes(Message)
            'Me._stream.BeginWrite(data, 0, data.Length, AddressOf DataSent, Nothing)
 
 
            ' String to store the response ASCII representation.
            Dim responseData As String
            Dim bytes As Int32
 
            If Me._client.Connected AndAlso Me._stream.CanRead AndAlso Me._stream.CanWrite Then
 
                Try
 
                    ' Translate the passed message into ASCII and store it as a Byte array.
                    Me._buffer = System.Text.Encoding.ASCII.GetBytes(Message)
 
                    Me._stream = Me._client.GetStream
 
                    With Me._stream
                        If .CanWrite AndAlso .CanRead Then
 
                            ' Send the message to the connected TcpServer. 
                            .Write(Me._buffer, 0, Me._buffer.Length)
                            '.BeginWrite(Me._buffer, 0, Me._buffer.Length, AddressOf DataSent, Nothing)
                            '.ReadTimeout = 30000
 
                            ReDim Me._buffer(Me._client.ReceiveBufferSize)
 
                            bytes = .Read(Me._buffer, 0, Me._buffer.Length)
 
                            ' Read the first batch of the TcpServer response bytes.
                            responseData = System.Text.Encoding.ASCII.GetString(Me._buffer, 0, bytes)
 
                            Return responseData
 
                        Else
                            Return String.Empty
                        End If
                    End With
 
                Catch ex As Exception
                    Return String.Empty
                End Try
 
            Else
                Return String.Empty
            End If
 
        End Function
 

fredericmazue

Quote:
à la 3e écriture, il me plante... la propriété "DataAvailable" du networkstream est à false... impossible d'avoir une réponse du serveur !

Sans doute ne respectes tu pas le protocole de communication du serveur (à propos duquel tu ne donnes aucun renseignements :( )
Je veux dire que peut être tu écris des données alors que tu devrais en lire, ou que tu en lis alors que tu devrais en écrire.
Difficile d'être plus précis sans infos sur le serveur, mais sur le principe c'est sûrement ça :)

dnx

Bonjour,

tout d'abord merci pour la réponse

en effet, j'aurais du vous donner plus d'infos sur le serveur

en fait... je ne sais que très peu de chose sur le serveur

=> il est ouvert en communication bi-directionnel sur le port 7001
et en telnet, je fais en commande line :

telnet server port
=> message : hello from server
getstatus
=> message : ok current read : ...
getstatus
=> message : ok current read : ...

donc ce que j'ai reproduis en .NET n'est qu'une communication bi-directionnelle en TCP via le tcpClient.
et cela marche pour :

=> message : hello from server
getstatus
=> message : ok current read : ...
getstatus
=> dataavailable = false!!!

:'(

j'ai retourné tout internet, je ne trouve rien de concret :(

fredericmazue

Quote:
j'ai retourné tout internet, je ne trouve rien de concret

Je maintiens ma suggestion.
J'avoue :oops: ne pas avoir lu ton code. Il est écrit en VB .Net et j'ai horreur de cette syntaxe, lourde, épaisse, inélégante, stupide, indigeste, pas belle, laide, hideuse, enfin bref tu vois ce que je veux dire.

Toutefois, il me semble avoir aperçu du coin de mon oeil porcin que ton tampon de lecture n'est dimensionné qu'une fois selon les données à lire au premier échange.
Si au second échange, et comme tu lis une seule fois en fonction de la taille du tampon, il y a plus de données à lire, elles restent dans le socket. Si à ce moment tu écris alors qu'il y a des données non lues, c'est la panique.

Je ne sais pas si ce que je dit est parfaitement exact, puisque je n'ai pas lu le code. Mais dans l'esprit, c'est ça, tu peux en être sûr.

telnet lui, lit les octets tant qu'il y en a à lire, à chaque coup.

dnx

Bonjour,

je suis débutant avec les stream et le tcpClient, je ne comprends pas trop les histoires de buffer/tampon

Pouvez-vous me donner un exemble? meme en C#?

merci d'avance

fredericmazue

Le code que tu as donné plus haut, c'est de la génération spontanée ?

Si les tampons sont un problème alors ne les utilises pas ! ;)

Lis les octets un à un tant qu'il y en a à lire

while (le_flux.DataAvailable)
read( un seul octet )

Avec les tampons c'est pareil d'ailleurs sur le principe. Simplement tu dois lire les octets par fournée (une fournée ayant la taille du tampon) TANT QUE il y en a à lire. Et vérifier à chaque lecture le nombre d'octets effectivement lus en testant la valeur retournée par read.

Ton problème est qu'il n'y a pas de boucle while dans ton code. Si j'en crois ce que j'ai aperçu du coin de mon oeil porcin.

dnx

Hello,

c'était à cause que le serveur ne répondait qu'après réception d'un carriage return et d'un linefeed...

mais ton idée était très bonne, vu que j'ai appris un peu plus sur les buffer et j'ai ajouté la boucle byte/byte!

un grand merci!!!

fredericmazue

Quote:
c'était à cause que le serveur ne répondait qu'après réception d'un carriage return et d'un linefeed...

Ah oui aussi.
Tous les protocoles en modes textes sont comme ça :)
Quand tu tapes "getstatus" dans telnet puis return, telent ajoute automatiquement \r\n

J'aurais pu te le suggérer. Mais comme tu n'as pas mis le message que tu envoyais dans ton code :twisted: ça aurait été plus de la divination qu'autre chose.