Tcplistener - deux exemples d'utilisation : avec et sans backgroundworker

Description

Cette petite solution en VB 2005 sans prétention montre comment utiliser
un tcplistener selon deux méthodes.
Donc j'ai crée deux classes générant des évennements.

La classe Ecouteur utilise un Backgroundworker pour utiliser le tcplistener sans geler la classe elle même ou le programme utilisant la classe.

La classe TcpListener utilise un timer pour surveiller la propriètè pending du tcplistener, ce qui ne gelepas non plus la classe elle même ou le programme utilisant la classe.

J'ai essayer de bien documenter les deux classes afin de bien comprendre comment fonctionne le TcpListener ainsi que le BackgroundWorker

En Exemple ci dessous la classe sans Backgroundworker

Source / Exemple :


Imports System.Net
Imports System.Net.Sockets
Imports System.ComponentModel
Imports System.io

Public Class Ecouteur
#Region "Déclarations locales"
    Private m_tcpl As TcpListener
    Private WithEvents m_thread As BackgroundWorker
    Private m_Etat As String
    Private Structure DtTcp 'Objet utiliser pour intercommunication entre thread et controle Ecouteur
        Dim sIP As IPAddress
        Dim sPort As Integer
        Dim sData As String
    End Structure
    Private m_dttcp As DtTcp
#End Region

#Region "Déclarations Evénements"
    Public Event ErreurEcouter(ByVal Msg As String)
    Public Event Etat(ByVal Etat As String)
    Public Event DonneeRecu(ByVal MessageRecu As String)
#End Region

    Public Sub New(ByVal IP As IPAddress, ByVal Port As Integer)
        m_dttcp.sIP = IP
        m_dttcp.sPort = Port
        m_dttcp.sData = ""
    End Sub

    Public Sub Ecouter()
        Try
            'Paramètrage du backgroundworker
            m_thread = New BackgroundWorker
            m_thread.WorkerReportsProgress = True
            m_thread.WorkerSupportsCancellation = True
            'Déclaration des procédure pour gérer les evenements du backgroundworker
            AddHandler m_thread.DoWork, AddressOf m_thread_DoWork
            AddHandler m_thread.ProgressChanged, AddressOf m_thread_ProgressChanged
            'Si pas déjà en execution lance le backgoundworker
            If Not m_thread.IsBusy Then m_thread.RunWorkerAsync(m_dttcp)
        Catch ex As Exception
            'Déclenche Evenement Erreur
            RaiseEvent ErreurEcouter(ex.Message)
        End Try
    End Sub

    Public Sub Arreter()
        Try
            'Demande l'arret par cancel du backgroundworker
            m_thread.CancelAsync()
            'Création d'un client local pour déclencher la boucle infinie du backgroundworker
            Dim TmpTcp As System.Net.Sockets.TcpClient
            Dim StrCli As System.Net.Sockets.NetworkStream
            Dim StrW As System.IO.StreamWriter
            TmpTcp = New System.Net.Sockets.TcpClient
            TmpTcp.Connect(m_dttcp.sIP, m_dttcp.sPort)
            StrCli = TmpTcp.GetStream()
            StrW = New System.IO.StreamWriter(StrCli)
            StrW.Write("truc pour declencher le AcceptTcpClient dans le thread")
            StrW.Close()
            StrCli.Close()
            TmpTcp.Close()
            'Déclenche Evenement Etat avec info déconnecté
            RaiseEvent Etat("Déconnecté")
        Catch ex As Exception
            'Déclenche Evenement Erreur
            RaiseEvent ErreurEcouter(ex.Message)
        End Try
    End Sub

#Region "Fonctions du thread"
    Private Sub m_thread_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles m_thread.DoWork
        'Recup Thread
        Dim LocThread As BackgroundWorker = CType(sender, BackgroundWorker)
        'Recup Data
        Dim LocDtTcp As DtTcp = e.Argument
        'Créer Composant
        m_tcpl = New TcpListener(LocDtTcp.sIP, LocDtTcp.sPort)
        Try
            Dim TcpCli As TcpClient
            Dim m_str As NetworkStream
            Dim m_read As StreamReader
            Dim msg As String
            While Not LocThread.CancellationPending 'Controle si arrêt demander
                m_tcpl.Start() 'Mise en attente de connection
                LocDtTcp.sData = "Attente connexion"
                LocThread.ReportProgress(1, LocDtTcp) 'Mise à jour Etat hors du thread
                '-------------------------------------------------------------------
                'Boucle de controle de demande connections entrantes ou d'annulation
                'Cette boucle a été supprimé et la procédure arreter modifiee pour déclencher le acceptcpclient
                'Car cette boucle utilisait des ressources processeurs non négligeable (freeze du thread)
                '                While True
                'If m_tcpl.Pending() Then Exit While
                'If LocThread.CancellationPending Then
                ' m_tcpl.Stop()
                ' Exit While
                ' End If
                'End While
                '-------------------------------------------------------------------
                TcpCli = m_tcpl.AcceptTcpClient() 'Créer un tcpclient pour récuperer les données
                LocDtTcp.sData = "Connecté"
                LocThread.ReportProgress(2, LocDtTcp) 'Mise à jour Etat hors du thread
                m_str = TcpCli.GetStream 'Recup des données envoyées
                m_read = New StreamReader(m_str) 'Lecteur du flux
                msg = m_read.ReadToEnd 'Recup des données envoyées
                m_read.Close()
                m_str.Close()
                LocDtTcp.sData = msg
                LocThread.ReportProgress(3, LocDtTcp) 'Transfert du message hors du thread
                m_tcpl.Stop()
            End While
            e.Cancel = True
        Catch ex As Exception
            m_tcpl.Stop()
            LocDtTcp.sData = "Erreur : " + ex.Message
            LocThread.ReportProgress(1, LocDtTcp)
        End Try
    End Sub

    Private Sub m_thread_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles m_thread.ProgressChanged
        Dim RepDtTcp As DtTcp = e.UserState
        If e.ProgressPercentage = 1 Then
            RaiseEvent Etat("Attente connection")
        ElseIf e.ProgressPercentage = 2 Then
            RaiseEvent Etat("Connecté")
        ElseIf e.ProgressPercentage = 3 Then
            RaiseEvent DonneeRecu(RepDtTcp.sData)
        End If
    End Sub

#End Region

End Class

Conclusion :


A vous d'exploiter cet exemple au mieux.

Je ne gère que de string en données envoyée / reçue, le but de l'exemple n'étant pas d'échanger tout type de données, mais de pouvoir établir une connection qui ne freeze pas l'application.)

Cordialement.

Codes Sources

A voir également

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.