TcpClientConnect.GetStream() [Résolu]

Marko007 96 Messages postés mardi 15 mai 2007Date d'inscription 29 janvier 2009 Dernière intervention - 25 juin 2008 à 15:12 - Dernière réponse : Marko007 96 Messages postés mardi 15 mai 2007Date d'inscription 29 janvier 2009 Dernière intervention
- 30 juin 2008 à 10:46
Bonjour,

je souhaite programmer un serveur TELNET avec TcpListener, TcpClient, NetworkStream,...

Avec ce programme ci-dessous, un client TELNET se connecte à mon programme, le prg reçoit les commandes
clavier du client, mais le programme passe ensuite (Après 2-3 cmdes) en non responding.
Je pense qu'avec l'utilisation de TIMER et GetStream cela ne fait pas bon ménage.

Comment éviter cela ?

----------------------------------------------------------------------------------------------
Imports System.Net.Sockets
Imports System.Net
Imports System.Text

Public Class Form1

    '********Déclaration de mes variables********
    Dim tcpClientConnect As TcpClient
    Dim port As Int32 = 23
    Dim localAddr As IPAddress = IPAddress.Parse("10.50.11.3")
    Dim TcpServer As New TcpListener(localAddr, port)
    Dim stream As NetworkStream

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    '********Activation du Timer TmrRefresh (Utilisé pour accepter la connexion du client)********
        TcpServer = Nothing
        TmrRefresh.Enabled = True
        TmrData.Enabled = False

        On Error GoTo ErroLoad
    '********Démarrage du TcpListener********
        TcpServer = Nothing
        TcpServer = New TcpListener(localAddr, port)
        TcpServer.Start()

        LblSckStatus.Text = "Server started at 10.50.11.3 / " & port

        Exit Sub

ErroLoad:
        MsgBox(Err.Number & " - " & Err.Description)

    End Sub

    Private Sub CmdQuit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CmdQuit.Click
    '********Arrêt du TcpServer + connexion avec client********
        tcpClientConnect.Close()
        TcpServer.Stop()

        TmrRefresh.Enabled = False
        TmrData.Enabled = False

        End

    End Sub

 
    Private Sub TmrRefresh_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TmrRefresh.Tick
'********Désactivation du Timer TmrRefresh (Utilisé pour accepter la connexion du client une seule fois !!)********
'********Activation du Timer TmrData(Utilisé pour lire les données du NetworkStream)********
        If TcpServer.Pending <> True Then
            tcpClientConnect = TcpServer.AcceptTcpClient
            LblSckStatus.Text = "Client accepted "
            TmrRefresh.Enabled = False
            TmrData.Enabled = True
        End If

    End Sub

    Private Sub TmrData_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TmrData.Tick
'********Lecture du NetworkStream, si donnée dispo...C'est ici que ça bug..********
        Dim i As Integer
        Dim bytes(1024) As [Byte]
        Dim data As [String] = Nothing

        i = 0
        stream = tcpClientConnect.GetStream()

        If tcpClientConnect.Connected AndAlso stream.CanRead AndAlso stream.CanWrite Then

            i = stream.Read(bytes, 0, bytes.Length)

            If i <> 0 Then
                data = Encoding.ASCII.GetString(bytes, 0, i)
                TxtData.Text = TxtData.Text + data & " - " & i

            End If
        End If

    End Sub
End Class

Merci,
Marco
Afficher la suite 

Votre réponse

9 réponses

Meilleure réponse
NHenry 14272 Messages postés vendredi 14 mars 2003Date d'inscription 15 octobre 2018 Dernière intervention - 26 juin 2008 à 15:47
3
Merci
Bonjour

Je ne voudrais pas dire de bêtise, mais je crois que :
i = stream.Read(bytes, 0, bytes.Length)

attend que tu ai reçu les 1025 (0 to 1024) octets avant de te rendre la main.

Pourquoi mettre "stream" en attribut alors d'une définition locale suffirait ?

Et accessoirement :
TxtData.Text = TxtData.Text + data & " - " & i
Peut être remplacé par :
TxtData.Text += data & " - " & i

L'ouverture d'esprit ne se limite pas toujours à une fracture du crâne.
VB (6, .NET1&2), C++, C#.Net1
Mo

Merci NHenry 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 96 internautes ce mois-ci

Commenter la réponse de NHenry
Meilleure réponse
NHenry 14272 Messages postés vendredi 14 mars 2003Date d'inscription 15 octobre 2018 Dernière intervention - 26 juin 2008 à 16:57
3
Merci
Bonjour

Mettre l'écoute sur un thread ...

L'ouverture d'esprit ne se limite pas toujours à une fracture du crâne.
VB (6, .NET1&2), C++, C#.Net1
Mo

Merci NHenry 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 96 internautes ce mois-ci

Commenter la réponse de NHenry
Meilleure réponse
NHenry 14272 Messages postés vendredi 14 mars 2003Date d'inscription 15 octobre 2018 Dernière intervention - 27 juin 2008 à 10:55
3
Merci
Bonjour,

Tu inaugures ma nouvelle signature .

A la place de ton Do/Loop sans condition, utilises comme condition de fin la prop Connected de ton TcpClient (note, pour détecter à coup sûr une déconnexion, il faut communiquer de temps en temps, avec un espace suivit d'un retour chariot, par exemple).

Et sitot que ton test détecte une déconnexion, il relance le thread d'écoute des connexions.

nota : Sleep est une méthode partagée, faire "trd1.Sleep(10)" ou "trd2.Sleep(10)" ou encore "Threading.Thread.Sleep(10)" c'est exactement la même chose, ça agit sur le même thread, à savoir le thread appelant..

http://nhen0039.chez-alice.fr/index.php

Merci NHenry 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 96 internautes ce mois-ci

Commenter la réponse de NHenry
Marko007 96 Messages postés mardi 15 mai 2007Date d'inscription 29 janvier 2009 Dernière intervention - 26 juin 2008 à 16:51
0
Merci
Bonjour,

Plus de bug, en utilisant un thread (Explications) :

Imports + Déclarations variables

Imports System.Threading

Private trd As Thread 'New thread
Dim Thrdata As [String] = Nothing 'New thread

Timer Refresh

 trd = New Thread(AddressOf  ThreadData)
 trd.IsBackground = True
 trd.Start()

Thread = ThreadData

 Private Sub ThreadData()
  Dim i As Integer
  Dim bytes(1024) As [Byte]

        Do
           i = 0

            stream = tcpClientConnect.GetStream()
            i = stream.Read(bytes, 0, bytes.Length)

            If i <> 0 Then

                Thrdata = Thrdata & Encoding.ASCII.GetString(bytes, 0, i)
                'Traitement ensuite de la variable globale ThrData

            End If
        Loop

 End Sub

Pour 1025 et stream, c'est parce que je dois pouvoir écrire et lire le stream (NetworkStream) ou pouvoir
faire autre chose avec ma tâche stype écouter un port série...

TxtData.Text += data & " - " & i, c'est plus propre en effet.

!!! J'ai un soucis : tant qu'un client telnet (Putty, MSDos : Telnet IP Adresse) n'est pas connecté,
la tâche est en attente... Cela est dû à ceci (Je pense) "If TcpServer.Pending <> True Then" (Dans un timer),
des idées pour ne pas perturber le fonctionnement de la tâche même si pas encore de client telnet connecté ?

Merci,
Marco
Commenter la réponse de Marko007
Marko007 96 Messages postés mardi 15 mai 2007Date d'inscription 29 janvier 2009 Dernière intervention - 27 juin 2008 à 10:20
0
Merci
Bien vu, je l'ai fait et ça marche nickel, merci.

Load de la Form

  trd1 = New Thread(AddressOf ThreadConn)
  trd1.IsBackground = True
  trd1.Start()
       
 trd2 = New Thread(AddressOf ThreadData)
 trd2.IsBackground = True
 trd2.Start()

Thread d'écoute de la connection

 Private Sub ThreadConn()

        If TcpServer.Pending <> True Then
            tcpClientConnect = TcpServer.AcceptTcpClient
            stream = tcpClientConnect.GetStream()
        End If

  End Sub

Comment puis-je suspendre dans mon code ma connection TcpListener, TcpClient, Threads (Si un client se déconnecte) et reprendre un nouveau ou même client qui se connecte par après ?

Merci,
Marco
Commenter la réponse de Marko007
NHenry 14272 Messages postés vendredi 14 mars 2003Date d'inscription 15 octobre 2018 Dernière intervention - 27 juin 2008 à 10:28
0
Merci
Bonjour

- Tu veux dire gérer les coupure accidentelle des connexion ?
Là, il faut enregistrer les données en stock et trouver un moyen de repérer à coup sûr (pour éviter certains type de pirates) le client pour restaurer les valeurs.

L'ouverture d'esprit ne se limite pas toujours à une fracture du crâne.
VB (6, .NET1&2), C++, C#.Net1
Mo
Commenter la réponse de NHenry
Marko007 96 Messages postés mardi 15 mai 2007Date d'inscription 29 janvier 2009 Dernière intervention - 27 juin 2008 à 10:44
0
Merci
Bonjour,

non c'est pour une coupure "voulue" par l'utilisateur. Et ensuite pour gérer, un reconnexion "voulue". Mais en laissant le TCPListener tjs
prêt à recevoir/écouter une nouvelle connexion.

Mon souci est que (Code du Bouton DISCONNECT CLIENT) :

tcpClientConnect.Close()     'Arrêt de la connexion du client
trd1.Abort()                         'Arrêt du Thread qui gère If TcpServer.Pending <> True then tcpClientConnect = TcpServer.AcceptTcpClienttrd2.Abort()                         'Arrêt du Thread qui gère stream <gras>tcpClientConnect.GetStream() / i stream.Read(bytes, 0, bytes.Length)</gras>
trd1.Sleep(2000)                 'Timer d'arrêt du thread qui gère la coonexion du client au TCPListener (Serveur d'écoute)
trd2.Sleep(2000)                 'Timer d'arrêt du thread qui gère la lecture du Networkstream (Canal entre serveur-client)
trd1.Start()                          'Démarrage du thread de connexion

En me déconnectant (Via un bouton DISCONNECT CLIENT), le thread trd2 tourne encore alors que pas de
client connecté (>> Lecture du NetworkStream qui bug forcèment) ...

Merci,
Marco
Commenter la réponse de Marko007
Marko007 96 Messages postés mardi 15 mai 2007Date d'inscription 29 janvier 2009 Dernière intervention - 27 juin 2008 à 16:21
0
Merci
Ok pour Threading.Thread.Sleep(1000)

J'ai solutionné mon souci avec "Try ... Catch" devant tcpClientConnect = TcpServer.AcceptTcpClient ettcpClientConnect.GetStream()

Lors d'un appel d'un thread à partir d'un évenement MSCOMM_EVENT (Je sais qu'il existe d'autre classe
port série, mais bon...), comment ensuite à la fin du thread rendre la main à l'évenement ?

Merci,
Marco
Commenter la réponse de Marko007
Marko007 96 Messages postés mardi 15 mai 2007Date d'inscription 29 janvier 2009 Dernière intervention - 30 juin 2008 à 10:46
0
Merci
Ok,

les évenements type MSCOMM_EVENT, TIMER_EVENT peuvent se déclencher avec l'utilisation des threads.
(Le bug était de mon côté) ;o)

Merci,
Marco
Commenter la réponse de Marko007

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.