Multi-Client mit TCPListener und TCPClient

Morgen!

Ähm, hast Du mal in den Thread geschaut, den ich im 9. Post gepostet hatte?
Definier einen Delegate, verknüpfe eine Methode damit und invoke den Delegate auf dem Form...
Wie gesagt ich kann kein VB aber ich versuchs mal *g*

Code:
Imports System.Net
Imports System.Net.Sockets

Public Class Form_Programm

    Dim ServerStatus As Integer = 0 '0=Offline 1=Online 2=Besetzt 3=AdminModus
    'Delegate definieren
    Delegate Sub SetTextCallback(ByVal [text] As String)

    'Programmstart:
    Private Sub Form_Programm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        If ServerStatus = 0 Then
            Button_Server.Text = "Server starten"
        Else
            Button_Server.Text = "Server anhalten"
        End If
        Call ServerOffline()
    End Sub

    'Buttons:
    Private Sub Button_Server_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Server.Click
        If ServerStatus = 0 Then
            Call ServerOnline()
        Else
            Call ServerOffline()
        End If
    End Sub
    Private Sub Button_LogLoeschen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_LogLoeschen.Click
        ListBox_Log.Items.Clear()
    End Sub

    'Funktionen:
    Private Sub ServerOnline()
        ServerStatus = 1
        ToolStripStatusLabel_ServerStatus.Text = "Online"
        ToolStripStatusLabel_ServerStatus.ForeColor = Color.Green
        Button_Server.Text = "Server anhalten"
        BackgroundWorker_TcpListener.RunWorkerAsync()
    End Sub

    Private Sub ServerOffline()
        ServerStatus = 0
        ToolStripStatusLabel_ServerStatus.Text = "Offline"
        ToolStripStatusLabel_ServerStatus.ForeColor = Color.Red
        Button_Server.Text = "Server starten"
        BackgroundWorker_TcpListener.CancelAsync()
    End Sub

    'BackgroundWorker:
    Private Sub BackgroundWorker_TcpListener_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker_TcpListener.DoWork
        Dim ipAdresse As IPAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList(0)
        Dim Port As Int32 = 12345
        Dim Server As New TcpListener(ipAdresse, Port)
        Server.Start()
        Do While ServerStatus = 1
            Dim Sitzung As Socket = Server.AcceptSocket
            'Aufruf der Methode
            SetText(Date.Now & " - Verbindung hergestellt")           
            Sitzung.Close()
        Loop
        Server.Stop()
    End Sub

    Private Sub SetText(ByVal [text] As String)
        'Wenn die ListBox in einem anderen Thread erstellt wurde
        If Me.ListBox_Log.InvokeRequired Then
            'Delegate mit der Methode verknüpfen
            Dim d As New SetTextCallback(AddressOf SetText)
            'Delegate auf dem Form invoken
            Me.Invoke(d, New Object() {[text]})
        'Eintrag speichern wenn die ListBox im aktuellen Thread erstellt wurde.
        Else
            ListBox_Log.Items.Add([text])
        End If
    End Sub
End Class
*hände waschen geh* :eek:
Hoffe dass das geht. Aber in dem Thread ists ja auch einfach beschrieben. ;)
Wirst es sicher hin bekommen.

Btw. für den Serverstaus kannst auch ein Enum verwenden...

MfG,
cosmo
 
Zuletzt bearbeitet:
Super! Das erste Problem ist behoben.
Der Code hat geholfen! Eine kleine Korrektur mußte ich nur machen:

Code:
Else
            ListBox_Log.Items.Add([text])
        End If
    End Sub
End Class

Mein nächstes Problem ist nun, das ich das starten und beenden des Backgroundworkers nicht richtig realisieren kann.
Ich lasse den TCPListener in einer Do Loop While Schleifen laufen. Wenn ich nun den Server "Offline" schalte, bleibt ja immer noch eine Warteschleife offen, bis er merkt, das er aufhören muß.

Code:
...
BackgroundWorker_TcpListener.RunWorkerAsync()
...
bzw.
...       
BackgroundWorker_TcpListener.CancelAsync()
...
 
Eine kleine Korrektur mußte ich nur machen
Ohh, hab das übersehen gehabt. :-(

Wenn ich nun den Server "Offline" schalte, bleibt ja immer noch eine Warteschleife offen, bis er merkt, das er aufhören muß.
Du meinst jetzt wenn Server.AcceptSocket immer noch blockt?

Definier den TCP Listener dafür innerhalb deines Forms und rufe die
TcpListener.Stop Methode innerhalb der ServerOffline Methode auf.
Aber noch bevor Du den ServerStatus auf 0 für Offline gesetzt hast damit der Loop beendet wird.
Also etwa so:
Code:
[...]
Dim Server As New TcpListener = null 'hoffe das ist so richtig
[...]

Private Sub ServerOffline()

    ServerStatus = 0
    Server.Stop()
    BackgroundWorker_TcpListener.CancelAsync()
    ToolStripStatusLabel_ServerStatus.Text = "Offline"
    ToolStripStatusLabel_ServerStatus.ForeColor = Color.Red
    Button_Server.Text = "Server starten"
End Sub

Private Sub BackgroundWorker_TcpListener_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker_TcpListener.DoWork

    Dim ipAdresse As IPAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList(0)
    Dim Port As Int32 = 12345
    Server As New TcpListener(ipAdresse, Port) 'hier einfach nur neu instanzieren
    Server.Start()
    Do While ServerStatus = 1
        Dim Sitzung As Socket = Server.AcceptSocket
        'Aufruf der Methode
        SetText(Date.Now & " - Verbindung hergestellt")
        Sitzung.Close()
    Loop
    If Server.Active
        Server.Stop()
    End If
End Sub
[...]
 
Also so bin ich erst mal zufrieden *G*:

Code:
Imports System.Net
Imports System.Net.Sockets

Public Class Form_Programm

    'Server definieren:
    Dim ipAdresse As IPAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList(0)
    Dim Port As Int32 = 22335
    Dim Server As New TcpListener(ipAdresse, Port)

    Dim ServerStatus As Integer = 0 '0=Offline 1=Online 2=AdminModus

    'Delegate definieren
    Delegate Sub SetTextCallback(ByVal [text] As String)

    'Programmstart:
    Private Sub Form_Programm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        If ServerStatus = 0 Then
            Button_Server.Text = "Server starten"
            Call ServerOffline()
        Else
            Button_Server.Text = "Server anhalten"
            Call ServerOnline()
        End If

    End Sub

    'Prgrammende:
    Private Sub Form_Programm_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        If BackgroundWorker_TcpListener.IsBusy Then
            BackgroundWorker_TcpListener.CancelAsync()
        End If
    End Sub

    'Buttons:
    Private Sub Button_Server_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Server.Click
        If ServerStatus = 0 Then
            Call ServerOnline()
        Else
            Call ServerOffline()
        End If
    End Sub
    Private Sub Button_LogLoeschen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_LogLoeschen.Click
        ListBox_Log.Items.Clear()
    End Sub

    'Funktionen:
    Private Sub ServerOnline()
        Server.Start()
        ServerStatus = 1
        ToolStripStatusLabel_ServerStatus.Text = "Online"
        ToolStripStatusLabel_ServerStatus.ForeColor = Color.Green
        Button_Server.Text = "Server anhalten"
        ListBox_Log.Items.Add(Date.Now & " - SERVER IST ONLINE")
        BackgroundWorker_TcpListener.RunWorkerAsync()
    End Sub

    Private Sub ServerOffline()
        Server.Stop()
        ServerStatus = 0
        ToolStripStatusLabel_ServerStatus.Text = "Offline"
        ToolStripStatusLabel_ServerStatus.ForeColor = Color.Red
        Button_Server.Text = "Server starten"
        ListBox_Log.Items.Add(Date.Now & " - SERVER IST OFFLINE")
        BackgroundWorker_TcpListener.CancelAsync()
    End Sub

    'BackgroundWorker:
    Private Sub BackgroundWorker_TcpListener_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker_TcpListener.DoWork

        Do While ServerStatus = 1
            Try
                Dim Sitzung As Socket = Server.AcceptSocket

                'Aufruf der Methode            
                SetText(Date.Now & " - Verbindung hergestellt")
                Sitzung.Close()
            Catch ex As Exception

            End Try
        Loop
    
    End Sub

    Private Sub SetText(ByVal [text] As String)
        'Wenn die ListBox in einem anderen Thread erstellt wurde        
        If Me.ListBox_Log.InvokeRequired Then
            'Delegate mit der Methode verknüpfen            
            Dim d As New SetTextCallback(AddressOf SetText)
            'Delegate auf dem Form invoken            
            Me.Invoke(d, New Object() {[text]})
        Else
            'Eintrag speichern wenn die ListBox im aktuellen Thread erstellt wurde. 
            ListBox_Log.Items.Add([text])
        End If
    End Sub
End Class

Eine Frage ist da aber noch..
muß ich bei einer Try Anweisung immer die Exception "verarbeiten"? Jetzt steht da ja nix drin und es geht alles.
Als nächstes werde ich mal testen, was passiert wenn ich einen Dateitransfer einbaue und sehen was passiert, wenn ich wärend der Übertragung den Server anhalte.
Bei Fragen werde ich mich wieder an Euch wenden :-)

Ich Danke jetzt schon mal für die viele Hilfe

Gruß Tomec
 
Also so bin ich erst mal zufrieden *G*
Das freut mich. Schön das Du am Ball geblieben bist. :)

muß ich bei einer Try Anweisung immer die Exception "verarbeiten"?
Du solltest die Exception schon behandeln. Du könnest innerhalb des catch Bocks
auf eine bestehende Internetverbindung prüfen und somit ermitteln, ob der Client
die Verbindung beendet hat oder ein anderer Grund dafür verantwortlich war.
Dann gibt es ja auch noch einen finally Block der Dir gelegenheit gibt,
nach dem Verlassen des try Blocks mögliche Resourcen zu schließen
oder speicherbereinigende Maßnahmen durch zu führen.
[thread=162023]Codenavigation durch Exceptions? - Thread[/thread]
[post=1274544]AW: ExeptionHandling und Weiter.....? - Post[/post]
[thread=213759]Fehlernummer - Thread[/thread]

Guck Dir an was für Exceptions geworfen werden. Das kannst auch in der MSDN nachlesen.
Bau für die Behandlung eine kleine Klasse wie in dem Oben beschriebenen Post.
Somit musst die Behandlung nicht für alle anderen derartigen Vorgänge nochmal implementieren.
 
Zurück