TCP Server/Client disconnect Probleme

  • VB.NET

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Dende().

    TCP Server/Client disconnect Probleme

    Hey Leute,

    ich habe ein Problem mit meinem TCP Chat nach 3 Tagen und viel gegoogle habe ich keine Lösung gefunden und hoffe jetzt das mir hier geholfen werden kann.

    Mein Problem besteht darin das der Server oder der Client probleme beim disconnecten hat, er sendet immer einen leeren Text mit dem Nicknamen davor, dazu erscheint noch eine Fehlermeldung im Server selbst.

    Bild1:


    Wenn ich beide disconnecte sendet er die ganze Zeit den Nicknamen...

    Bild2:


    Hier der Server:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Net.Sockets
    2. Imports System.IO
    3. Imports System.Net
    4. Module Module1
    5. Private mobjTCPServer As TcpListener
    6. Private mobjClient As New TcpClient
    7. Private mobjIpEndpoint As IPEndPoint = New IPEndPoint(IPAddress.Any, 8888) ' eingestellt ist port 8888
    8. Private mobjList As New List(Of clsConnection)
    9. Private mobjClientConnection As clsConnection
    10. Private mobjThreadToCloseServer As New Threading.Thread(AddressOf CloseServer)
    11. Sub Main()
    12. Try
    13. mobjThreadToCloseServer.Start()
    14. mobjTCPServer = New TcpListener(mobjIpEndpoint)
    15. mobjTCPServer.Start()
    16. Console.WriteLine("Server is running!")
    17. While True 'warten auf eine neue verbindung...
    18. mobjClient = mobjTCPServer.AcceptTcpClient
    19. Dim objConnect As New clsConnection(mobjClient.GetStream) ' und erstellen für die neue verbindung eine neue connection...
    20. objConnect.Stream = mobjClient.GetStream
    21. objConnect.StreamReader = New StreamReader(objConnect.Stream)
    22. objConnect.StreamWriter = New StreamWriter(objConnect.Stream)
    23. objConnect.Nick = objConnect.StreamReader.ReadLine 'Nickname wird übergeben
    24. mobjList.Add(objConnect) ' und fügen sie der liste der clients hinzu.
    25. Console.WriteLine(objConnect.Nick & " has joined.")
    26. For Each mobjClientConnection In mobjList ' an alle clients weitersenden.
    27. Try
    28. mobjClientConnection.StreamWriter.WriteLine(objConnect.Nick & " has joined :)")
    29. mobjClientConnection.StreamWriter.Flush()
    30. Catch ex As SocketException
    31. ' NOP
    32. Catch ex As Exception
    33. Console.WriteLine(ex.ToString)
    34. End Try
    35. Next
    36. Dim objThread As New Threading.Thread(AddressOf ListenToConnection)
    37. objThread.Start(objConnect)
    38. End While
    39. Catch ex As Exception
    40. Console.WriteLine(ex.ToString)
    41. End Try
    42. End Sub
    43. Private Sub ListenToConnection(ByVal con As Object)
    44. Dim objConnect As clsConnection = CType(con, clsConnection)
    45. Do
    46. Try
    47. Dim strTmp As String = objConnect.StreamReader.ReadLine ' warten, bis etwas empfangen wird...
    48. Console.WriteLine(objConnect.Nick & ": " & strTmp)
    49. For Each mobjClientConnection In mobjList ' an alle clients weitersenden.
    50. Try
    51. If mobjClient.Connected Then
    52. mobjClientConnection.StreamWriter.WriteLine(objConnect.Nick & ": " & strTmp)
    53. mobjClientConnection.StreamWriter.Flush()
    54. Else
    55. End If
    56. Catch ex As SocketException
    57. mobjClientConnection.StreamWriter.WriteLine(objConnect.Nick & " leaved the Chat :(")
    58. mobjClientConnection.StreamWriter.Flush()
    59. Catch ex As Exception
    60. Console.WriteLine(ex.ToString)
    61. End Try
    62. Next
    63. Catch
    64. 'mobjClientConnection.StreamWriter.WriteLine(objConnect.Nick & " leaved the Chat :(")
    65. mobjList.Remove(objConnect)
    66. Console.WriteLine(objConnect.Nick & " has exit.")
    67. Exit Do
    68. End Try
    69. Loop
    70. End Sub
    71. Private Sub CloseServer(ByVal con As Object)
    72. Do
    73. Dim strClosing As String
    74. Dim intCount As Int32
    75. Console.WriteLine("Pls type exit to close the Server")
    76. strClosing = Console.ReadLine()
    77. If strClosing = "exit" Then
    78. mobjTCPServer.Stop()
    79. End
    80. End If
    81. If strClosing = "test" Then
    82. For Each mobjClientConnection In mobjList
    83. intCount += 1
    84. Next
    85. Console.WriteLine(intCount & " Chatter online")
    86. intCount = 0
    87. End If
    88. Loop
    89. End Sub
    90. End Module
    91. #Region "clsConnection"
    92. Public Class clsConnection
    93. Private mobjStream As NetworkStream
    94. Private mobjStreamWriter As StreamWriter
    95. Private mobjStreamReader As StreamReader
    96. Private strNick As String
    97. Public Sub New(ByVal objStream As NetworkStream)
    98. mobjStream = objStream
    99. End Sub
    100. Public Property Stream() As NetworkStream
    101. Get
    102. Return mobjStream
    103. End Get
    104. Set(ByVal value As NetworkStream)
    105. mobjStream = value
    106. End Set
    107. End Property
    108. Public Property StreamWriter() As StreamWriter
    109. Get
    110. Return mobjStreamWriter
    111. End Get
    112. Set(ByVal value As StreamWriter)
    113. mobjStreamWriter = value
    114. End Set
    115. End Property
    116. Public Property StreamReader() As StreamReader
    117. Get
    118. Return mobjStreamReader
    119. End Get
    120. Set(ByVal value As StreamReader)
    121. mobjStreamReader = value
    122. End Set
    123. End Property
    124. Public Property Nick() As String
    125. Get
    126. Return strNick
    127. End Get
    128. Set(ByVal value As String)
    129. strNick = value
    130. End Set
    131. End Property
    132. End Class
    133. #End Region



    hier der Client:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Net.Sockets
    2. Imports System.IO
    3. Public Class frmClient
    4. Private mobjStream As NetworkStream
    5. Private mobjStreamWriter As StreamWriter
    6. Private mobjStreamReader As StreamReader
    7. Private mobjClient As New TcpClient
    8. Private mobjThead As Threading.Thread
    9. Private Delegate Sub DAddItem(ByVal s As String)
    10. Private mobjNick As String = "unknown"
    11. Private Sub AddItem(ByVal strText As String)
    12. rtfChat.Text += strText & vbCrLf
    13. End Sub
    14. Private Sub Listen()
    15. While mobjClient.Connected
    16. If mobjClient.Connected Then
    17. Try
    18. Me.Invoke(New DAddItem(AddressOf AddItem), mobjStreamReader.ReadLine)
    19. Catch
    20. If Not mobjClient.Connected Then
    21. 'Message()
    22. If btnDisconnect.Enabled = True Then
    23. MessageBox.Show("Verbindung zum Server abgebrochen!", "ThiZ Chat", MessageBoxButtons.OK)
    24. End If
    25. Else
    26. End If
    27. End Try
    28. End If
    29. End While
    30. End Sub
    31. Private Sub frmClient_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
    32. mobjStream.Close()
    33. mobjClient.Close()
    34. End Sub
    35. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    36. mobjNick = InputBox("Nickname: ", "Namen festlegen", "Chatter")
    37. End Sub
    38. Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
    39. Try
    40. If Not txtSend.Text = "" Then
    41. If mobjClient.Connected Then
    42. mobjStreamWriter.WriteLine(txtSend.Text)
    43. mobjStreamWriter.Flush()
    44. txtSend.Clear()
    45. Else
    46. Message()
    47. End If
    48. End If
    49. Catch ex As Exception
    50. HandleException(ex.ToString)
    51. End Try
    52. End Sub
    53. Private Sub txtSend_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtSend.KeyDown
    54. Try
    55. If e.KeyCode = Keys.Enter Then
    56. e.SuppressKeyPress = True
    57. btnSend_Click(sender, e)
    58. End If
    59. Catch ex As Exception
    60. HandleException(ex.ToString)
    61. End Try
    62. End Sub
    63. Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
    64. Try
    65. btnConnect.Enabled = False
    66. btnDisconnect.Enabled = True
    67. If txtServerIP.Text = "" Then
    68. MsgBox("Keine IP eingetragen!", "ThiZ Chat", MessageBoxButtons.OK)
    69. Else
    70. mobjClient = New TcpClient
    71. mobjClient.Connect(txtServerIP.Text, 8888) ' hier die ip des servers eintragen.
    72. End If
    73. If mobjClient.Connected Then
    74. mobjStream = mobjClient.GetStream
    75. mobjStreamWriter = New StreamWriter(mobjStream)
    76. mobjStreamReader = New StreamReader(mobjStream)
    77. mobjStreamWriter.WriteLine(mobjNick)
    78. mobjStreamWriter.Flush()
    79. mobjThead = New Threading.Thread(AddressOf Listen)
    80. mobjThead.Start()
    81. Else
    82. Message()
    83. End If
    84. Catch ex As Exception
    85. HandleException(ex.ToString)
    86. btnConnect.Enabled = True
    87. End Try
    88. txtSend.Focus()
    89. End Sub
    90. Private Sub btnDisconnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisconnect.Click
    91. Try
    92. btnDisconnect.Enabled = False
    93. btnConnect.Enabled = True
    94. mobjStream.Close()
    95. mobjClient.Close()
    96. Catch ex As Exception
    97. HandleException(ex.ToString)
    98. btnDisconnect.Enabled = True
    99. End Try
    100. End Sub
    101. Private Sub rtfChat_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles rtfChat.TextChanged
    102. rtfChat.SelectionStart = rtfChat.Text.Length
    103. rtfChat.ScrollToCaret()
    104. End Sub
    105. Private Sub Message()
    106. MessageBox.Show("Keine Verbindung zum Server", "ThiZ Chat", MessageBoxButtons.OK)
    107. End Sub
    108. Private Sub HandleException(ByVal e As String)
    109. MsgBox(e, MsgBoxStyle.Information, "Fehler")
    110. End Sub
    111. End Class



    Danke für eure Hilfe :)

    Mfg

    Dende()
    Den Fehler kennen wir bereits =)

    Ist immer im Multiserver. Wenn ich mich recht entsinne wird auf dem Server die TCP Verbindung nicht korrekt geschlossen, der (nicht vorhandene) Buffer gelesen, und dann gibts so einen Blödsinn.
    Also TCP Stream schließen und dann die Connection aus der List schmeißen.

    Gruß,
    Manawyrm

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

    THX Manawyrm für die schnelle Hilfe :)

    Das Problem auf Bild 2 hab ich jetzt gelöst mit einem einfachen

    Exit Do

    weil es sonst ne Endlosschleife war...
    Beim anderen bin ich noch bei, ich denke mein Problem ist auch noch das ich nicht so ganz raffe was genau da passiert, aber ich denke das bekomm ich noch hin


    Spoiler anzeigen

    VB.NET-Quellcode

    1. If mobjClient.Connected Then
    2. mobjClientConnection.StreamWriter.WriteLine(objConnect.Nick & ": " & strTmp)
    3. mobjClientConnection.StreamWriter.Flush()
    4. Else
    5. Exit Do
    6. End If





    Edit:

    Habe meine Probleme soweit behoben, allerdings habe ich dadurch wieder andere Fehler bekommen :D
    Wenn ich jetzt disconnecte zeigt er es richtig an, aber er sendet es den Clienten nur einmal bzw bei 3 Clienten sendet er es nur einem Clienten...
    Das ist echt zum Mäuse melken :/

    Neuer ServerQuelltext:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub ListenToConnection(ByVal con As Object)
    2. Dim objConnect As clsConnection = CType(con, clsConnection)
    3. Do
    4. Try
    5. Dim strTmp As String = objConnect.StreamReader.ReadLine ' warten, bis etwas empfangen wird...
    6. '------------------------------------------------ ===== NEU ===== -----------------------------------------------------------
    7. If strTmp = Nothing Then
    8. mobjClientConnection.StreamWriter.WriteLine(objConnect.Nick & " disconnected")
    9. mobjClientConnection.StreamWriter.Flush()
    10. Exit Do
    11. '------------------------------------------------ ===== NEU ===== -----------------------------------------------------------
    12. End If
    13. Console.WriteLine(objConnect.Nick & ": " & strTmp)
    14. For Each mobjClientConnection In mobjList ' an alle clients weitersenden.
    15. Try
    16. If mobjClient.Connected Then
    17. mobjClientConnection.StreamWriter.WriteLine(objConnect.Nick & ": " & strTmp)
    18. mobjClientConnection.StreamWriter.Flush()
    19. Else
    20. Exit Do
    21. End If
    22. Catch ex As SocketException
    23. 'NOP
    24. Catch ex As Exception
    25. Console.WriteLine(ex.ToString)
    26. End Try
    27. Next
    28. Catch
    29. mobjList.Remove(objConnect)
    30. Console.WriteLine(objConnect.Nick & " has exit.")
    31. Exit Do
    32. End Try
    33. Loop
    34. mobjList.Remove(objConnect)
    35. Console.WriteLine(objConnect.Nick & " has exit.")
    36. End Sub



    Mfg
    Dende()
    :)

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

    VB.NET-Quellcode

    1. For Each mobjClientConnection In mobjList ' an alle clients weitersenden.
    2. Try
    3. If mobjClient.Connected Then
    4. mobjClientConnection.StreamWriter.WriteLine(objConnect.Nick & ": " & strTmp)
    5. mobjClientConnection.StreamWriter.Flush()
    6. Else
    7. Exit Do '<- MARKIERTE STELLE ^^
    8. End If
    9. Catch ex As SocketException
    10. 'NOP
    11. Catch ex As Exception
    12. Console.WriteLine(ex.ToString)
    13. End Try
    14. Next


    Das mit der Schleife macht er ja ... Nur das Problem ist die Markierte Stelle. Er hat den Client der die Verbindung getrennt hat noch in der Liste, und versucht an diesen zu senden. Schlägt fehl weil nicht mehr verbunden, und durch die abfrage If mobjClient.Connected Then beendet er den kompletten Thread.
    Hey Leute,

    THX für die Antworten :)

    Ich habe jetzt die Lösung dank euch und eines Arbeitskollgen

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub ListenToConnection(ByVal objConnection As Object)
    2. Dim objConnect As clsConnection = CType(objConnection, clsConnection)
    3. Dim blnListen As Boolean = True ' <--- Neu
    4. Do
    5. Dim strMessage As String = objConnect.StreamReader.ReadLine ' warten, bis etwas empfangen wird...
    6. If strMessage = String.Empty Then
    7. strMessage = "disconnected"
    8. mobjList.Remove(objConnect)
    9. blnListen = False '<-- auf Flase
    10. End If
    11. Console.WriteLine(objConnect.Nick & ": " & strMessage)
    12. For Each mobjClientConnection In mobjList ' an alle clients weitersenden.
    13. Try
    14. If mobjClient.Connected Then
    15. mobjClientConnection.StreamWriter.WriteLine(objConnect.Nick & ": " & strMessage)
    16. mobjClientConnection.StreamWriter.Flush()
    17. Else
    18. blnListen = False '<---
    19. End If
    20. Catch ex As Exception
    21. Console.WriteLine(ex.ToString)
    22. End Try
    23. Next
    24. Loop While blnListen '<-- Hier die Whileschleife
    25. Console.WriteLine(objConnect.Nick & " has exit.")
    26. End Sub


    Exit Do wurde durch eine variable blnListen = true und einer Whileschleife ersetzt, dadurch wird die schleife nicht sofort abgebrochen und es kann an alle Clienten die Medlung gesendet werden :D

    Mfg
    Dende()
    :thumbsup: