TCP/IP - Probleme mit ListenThread

  • VB.NET

Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von luckay.

    TCP/IP - Probleme mit ListenThread

    Hallo,

    ich erstelle momentan ein Programm, mit dem ich Telegramme (in Bytes) an einen Clienten versende, der mir automatisch 2 Telegramme zurück sendet.
    Das Programm beinhaltet einen ListenThread, der solange eine Verbindung besteht, Telegramme empfangängt und diese in einem "Monitor" ausgibt.
    Ich hatte die ganze Zeit Probleme damit, nach dem disconnecten zum Clienten wieder zu reconnecten. Die Lösung zu diesem Problem habe ich hier im Forum gefunden, jedoch macht der ListenThread nun Probleme.
    Ich muss diesen bevor ich bevor ich die Verbindung trenne "aborten", weil ansonsten der Thread hängen bleibt nachdem ich den Stream und Clienten beende und folgende Fehlermeldung im ListenThread erhalte:
    Fehlermeldung 1:
    Eine Ausnahme (erste Chance) des Typs "System.IO.IOException" ist in System.dll aufgetreten.

    Wenn ich nun reconnecten will, nachdem der Thread abgebrochen wurde, kommt folgende Fehlermeldung im Privat Sub "Connect":
    Fehlermeldung 2:
    Ausnahme:Ausgelöst: "Der Thread wird ausgeführt oder wurde abgebrochen. Neustart nicht möglich." (System.Threading.ThreadStateException)
    System.Threading.ThreadStateException wurde ausgelöst: "Der Thread wird ausgeführt oder wurde abgebrochen. Neustart nicht möglich."

    Wie kann ich das nun mit dem Thread regeln, das dieser nach einem reconnect wieder läuft?

    Hier die "Codeschnipsel":
    Initialisierungen nach Public Class:

    VB.NET-Quellcode

    1. Dim Client As New Net.Sockets.TcpClient
    2. Dim Stream As NetworkStream = Nothing
    3. Private ListenTCPIPThread As New Thread(AddressOf ListenTCPIP)
    4. Private ReceiveBytesTCPIP(Client.ReceiveBufferSize) As Byte
    5. Private bListenTCPIP As Boolean
    6. Private bNewTCPIP As Boolean


    ListenThread:

    VB.NET-Quellcode

    1. Public Delegate Function refreshMonitorDel(ByVal lstnng As String)
    2. Public Function refreshMonitor(ByVal lstnng As String)
    3. Try
    4. Me.txtAnzeige.AppendText(DateTime.Now & " : " & "Recieved: " + lstnng + vbCrLf)
    5. Catch ex As Exception
    6. txtAnzeige.AppendText(DateTime.Now & " : " & "Failure." + vbCrLf)
    7. End Try
    8. Return Nothing
    9. End Function
    10. Sub ListenTCPIP()
    11. While bListenTCPIP
    12. Dim thrdAnswer As Integer
    13. Dim lLoop As Short = 0
    14. While lLoop < 2
    15. Dim strTmp As String = ""
    16. thrdAnswer = Stream.Read(ReceiveBytesTCPIP, 0, Client.ReceiveBufferSize) 'FEHLERMELDUNG 1
    17. For i = 0 To ReceiveBytesTCPIP(1) - 1
    18. strTmp += "." + ReceiveBytesTCPIP(i).ToString("X2")
    19. Next
    20. If Me.txtAnzeige.InvokeRequired Then
    21. Me.Invoke(New refreshMonitorDel(AddressOf refreshMonitor), New Object() {strTmp})
    22. Else
    23. Me.txtAnzeige.AppendText(DateTime.Now & " : " & "Recieved: " + strTmp + vbCrLf)
    24. End If
    25. lLoop += 1
    26. End While
    27. End While
    28. End Sub


    Connect:

    VB.NET-Quellcode

    1. Dim Client As New Net.Sockets.TcpClient
    2. txtAnzeige.AppendText(DateTime.Now & " : " & "Attempting To Connect..." + vbCrLf)
    3. Try
    4. Client.Connect("172.24.55.186", 10000)
    5. Catch ex As SystemException
    6. bListenTCPIP = False
    7. Stream.Close()
    8. Client.Close()
    9. txtAnzeige.AppendText(DateTime.Now & " : " & "Connection Fails" + vbCrLf)
    10. Exit Sub
    11. End Try
    12. If Client.Connected Then
    13. Stream = Client.GetStream()
    14. bListenTCPIP = True
    15. ListenTCPIPThread.Start() 'FEHLERMELDUNG 2
    16. txtAnzeige.AppendText(DateTime.Now & " : " & "Connected" + vbCrLf)
    17. End If
    18. End Sub


    Disconnect

    VB.NET-Quellcode

    1. bListenTCPIP = False
    2. Try
    3. ListenTCPIPThread.Abort()
    4. Catch ex As SystemException
    5. End Try
    6. Try
    7. Stream.Close()
    8. Catch ex As SystemException
    9. txtAnzeige.AppendText(DateTime.Now & " : " & "Closing stream failed." + vbCrLf)
    10. Exit Sub
    11. End Try
    12. txtAnzeige.AppendText(DateTime.Now & " : " & "Stream closed." + vbCrLf)
    13. Try
    14. Client.Close()
    15. Catch ex As SystemException
    16. txtAnzeige.AppendText(DateTime.Now & " : " & "Disconnecting failed." + vbCrLf)
    17. Exit Sub
    18. End Try
    19. txtAnzeige.AppendText(DateTime.Now & " : " & "Connection closed." + vbCrLf)
    20. End Sub



    Sollte ich etwas unverständlich ausgedrückt haben oder Details die benötigt werden fehlen, einfach bescheid geben.
    Danke euch schonmal für die Hilfe!

    Gruß,
    luckay
    @singu:
    Die Fehlermeldung eins ist mit einem Kommentar im Code von "Connect" markiert, du musst nur etwas zur Seite scrollen.

    @jvbsl:
    Ich habs jetzt im Privat Sub Connect eingefügt

    VB.NET-Quellcode

    1. Dim Client As New Net.Sockets.TcpClient
    2. ListenTCPIPThread = New Thread(AddressOf ListenTCPIP)

    und er startet den Thread. Jedoch macht mir der ListenThread dann Ärger, genau an der Stelle an welcher auch die Fehlermeldung 1 auftaucht (Stream.Reader)
    Ausnahme:Ausgelöst: "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt." (System.NullReferenceException)
    System.NullReferenceException wurde ausgelöst: "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."

    Zur Ausnahme finde ich jedoch keine Erläuterung in der MSDN Library ... liegt bestimmt daran das der reader nicht sofort etwas empfängt, aber das tut er beim ersten connect auch nicht. Kann mir jemand weiterhelfen?

    jvbsl schrieb:

    dann setz mal nen Haltepunkt und gucke, welches Objekt Nothing ist...

    Ist vermutlich eh der Stream, der ja beim Abort geschlossen wurde.

    Würde das Ganze etwas besser strukturieren und den Connect und das Listen in den gleichen Thread packen. Ausserdem prüft man bitte nicht immer nur auf Exception, sondern gezielt auf die Exception die man abfangen will.
    Edit: war falsch^^

    ich sehe gerade, dass das Client und Server getrennt waren...

    also musst du diesen Listenthread schließen und erst den nächsten neuen starten, wenn ein Client akzeptiert wurde also über AcceptClient oder BeginAccept...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „jvbsl“ ()

    doch die codes sind vollständig. was sollte ich eingebaut haben?

    Stand bisher ist folgender:
    ich kann reconnecten und er startet den ListenThread wo er dann aber bei

    VB.NET-Quellcode

    1. thrdAnswer = Stream.Read(ReceiveBytesTCPIP, 0, Client.ReceiveBufferSize)

    in der "Sub ListenTCPIP()" hängen bleibt.
    Dort erhalte ich folgende Fehlermeldung:
    Ausnahme:Ausgelöst: "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt." (System.NullReferenceException)
    System.NullReferenceException wurde ausgelöst: "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."

    Das Eigenartige hierbei ist, das mein ReceiveBytesTCPIP die als letztes gesendeten Bytes (vor dem disconnect) noch enhält ... weshalb wohl die Fehlermeldung erscheint.
    das ganze sieht in so aus:

    VB.NET-Quellcode

    1. Imports System.Net
    2. Imports System.Net.Sockets
    3. Imports System.IO
    4. Imports System.Threading
    5. Imports System.Text
    6. Imports Microsoft.VisualBasic
    7. Public Class Form1
    8. Dim Client As New Net.Sockets.TcpClient
    9. Dim Stream As NetworkStream = Nothing
    10. Private ListenTCPIPThread As New Thread(AddressOf ListenTCPIP)
    11. Private ReceiveBytesTCPIP(Client.ReceiveBufferSize) As Byte
    12. Private bListenTCPIP As Boolean
    13. Private bNewTCPIP As Boolean
    14. 'START LISTENTHREAD
    15. Public Delegate Function refreshMonitorDel(ByVal lstnng As String)
    16. Public Function refreshMonitor(ByVal lstnng As String)
    17. Try
    18. Me.txtAnzeige.AppendText(DateTime.Now & " : " & "Recieved: " + lstnng + vbCrLf)
    19. Catch ex As Exception
    20. txtAnzeige.AppendText(DateTime.Now & " : " & "Failure." + vbCrLf)
    21. End Try
    22. Return Nothing
    23. End Function
    24. Sub ListenTCPIP()
    25. While bListenTCPIP
    26. Dim thrdAnswer As Integer
    27. Dim lLoop As Short = 0
    28. While lLoop < 2
    29. Dim strTmp As String = ""
    30. thrdAnswer = Stream.Read(ReceiveBytesTCPIP, 0, Client.ReceiveBufferSize) 'FEHLERMELDUNG
    31. For i = 0 To ReceiveBytesTCPIP(1) - 1
    32. strTmp += "." + ReceiveBytesTCPIP(i).ToString("X2")
    33. Next
    34. If Me.txtAnzeige.InvokeRequired Then
    35. Me.Invoke(New refreshMonitorDel(AddressOf refreshMonitor), New Object() {strTmp})
    36. Else
    37. Me.txtAnzeige.AppendText(DateTime.Now & " : " & "Recieved: " + strTmp + vbCrLf)
    38. End If
    39. lLoop += 1
    40. End While
    41. End While
    42. End Sub
    43. 'ENDE LISTENTHREAD
    44. Private Sub cmdOpen_Click()
    45. Dim Client As New Net.Sockets.TcpClient
    46. txtAnzeige.AppendText(DateTime.Now & " : " & "Attempting To Connect..." + vbCrLf)
    47. Try
    48. Client.Connect("172.24.55.186", 10000)
    49. Catch ex As SystemException
    50. bListenTCPIP = False
    51. Stream.Close()
    52. Client.Close()
    53. txtAnzeige.AppendText(DateTime.Now & " : " & "Connection Fails" + vbCrLf)
    54. Exit Sub
    55. End Try
    56. If Client.Connected Then
    57. Stream = Client.GetStream()
    58. bListenTCPIP = True
    59. ListenTCPIPThread = New Thread(AddressOf ListenTCPIP)
    60. ListenTCPIPThread.Start()
    61. txtAnzeige.AppendText(DateTime.Now & " : " & "Connected" + vbCrLf)
    62. End If
    63. End Sub
    64. Private Sub cmdClose_Click()
    65. bListenTCPIP = False
    66. Try
    67. ListenTCPIPThread.Abort()
    68. Catch ex As SystemException
    69. End Try
    70. Try
    71. Stream.Close()
    72. Catch ex As SystemException
    73. txtAnzeige.AppendText(DateTime.Now & " : " & "Closing stream failed." + vbCrLf)
    74. Exit Sub
    75. End Try
    76. txtAnzeige.AppendText(DateTime.Now & " : " & "Stream closed." + vbCrLf)
    77. Try
    78. Client.Close()
    79. Catch ex As SystemException
    80. txtAnzeige.AppendText(DateTime.Now & " : " & "Disconnecting failed." + vbCrLf)
    81. Exit Sub
    82. End Try
    83. txtAnzeige.AppendText(DateTime.Now & " : " & "Connection closed." + vbCrLf)
    84. End Sub
    und da haben wir das Problem :P ich hab gedacht das eine wäre Server und das andere Client...
    Dim Client As New Net.Sockets.TcpClient
    in cmdOpen_Click->
    Client = New Net.Sockets.TcpClient
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    yeah, super ... es läuft :)
    Vielen Dank!

    Hätte noch ne Frage bzgl. dem Client.Connect:
    Wenn ich eine IP-Adresse eingebe die nicht vorhanden ist/mit der er sich nicht verbinden kann, dann stürzt das Programm ab ... ohne jegliche Meldung. Das war vorher nicht der fall da hat er immer brav "Connecting failed" ausgegeben. Woran könnte das liegen?
    vor:
    Stream.Close()
    Client.Close()
    im Catch Block solltest du überprüfen ob das überhaupt möglich ist, also ob Stream nicht Nothing ist und ob Client auch nicht Nothing ist...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    wenn sie nicht verbunden sind ja, aber nicht wenn diese Nothing sind, weil dann bekommst du eine NullReferenceException, aus diesem Grund wird der Code nicht vollständig zu ende geführt...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    hallo,

    hatte dieses problem (mit dem client.connect) hinten angestellt, weil es nicht direkt bewältigen konnte ... jedoch ist mein programm nun soweit fertig, bis auf diesen bug.
    wenn die falsche ip eingegeben wird bzw. das programm nicht connecten kann hängt es sich auf.
    komme einfach nicht dahinter wie ich diese abfrage "ob stream/client nothing ist" realsieren kann?
    kann mir hierbei jemand weiterhelfen?


    vielen dank
    luckay
    If stream is Nothing? oder If client Is Nothing^^

    du kannst auch einfach einen Try Catch block machen:

    VB.NET-Quellcode

    1. Try
    2. 'hier der Code zum verbinden
    3. Catch ex As Exception
    4. MsgBox(ex.Message)
    5. End Try

    was zwischen Try und Catch steht wird probiert auszuführen, falls ein Fler auftritt springt es in Catch und gibt hier die Fehlermeldung aus(kannste auch ersetzen...)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---