TcpClient Problem

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von ViktorS.

    TcpClient Problem

    Hi,

    ich schreibe ein Chatprogramm für das Pain and Paper Spiel DSA, dazu benutze ich einen TCP Listener und TCP Client, und ich bin gerade bei dem Client.

    Für die Kommunikation schreibe ich ein kleines Protokoll, bisher kann es nur registrieren und anmelden, doch jedes Mal, wenn der Client vom Server die Nachricht erhält, dass die Registration bzw. der LogIn erfolgreich war, sollte die Registrationsform geschlossen bzw. die Login form unsichtbar gemacht werden und eine ChatRoom form auftauchen. Das passier auch, doch die Registrations form bzw. LogIn form bleibt da und reagiert weiterhin, die ChatRoom from taucht auf ist aber "Keine Rückmeldung".

    Ich habe schon alles ausprobiert, aber ich kriege einfach nicht heraus, worand das liegt und komme deshalb auch nicht drauf, wie man es beheben kann.

    Hier ist der Quellcode:
    User Klasse
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class User
    2. Class Account
    3. Public Shared Property Username As String = Nothing
    4. Public Shared Property Password As String = Nothing
    5. Public Shared Property EMail As String = Nothing
    6. Public Shared Property ID As UInteger = Nothing
    7. End Class
    8. Class Chat
    9. Public Shared Property ChatView As String
    10. Public Shared Property Users As New ListBox
    11. End Class
    12. Class Control
    13. Private Shared ACL As New List(Of String)
    14. Public Shared Sub AddAllowedChars()
    15. With ACL
    16. .Add("A")
    17. 'Die Liste ist länger, habe die nur entfernt, damit es nicht si viele Zeichen sind.
    18. .Add("@")
    19. End With
    20. End Sub
    21. Public Shared Function CheckAccInfoIsOk(ByVal AccInfo As String) As Boolean
    22. Dim Chr As Char() = AccInfo.ToCharArray
    23. For i As Byte = 0 To UBound(Chr)
    24. For Each aChr As String In ACL
    25. If Chr(i) = aChr Then
    26. Exit For
    27. ElseIf aChr = "@" Then
    28. Return False
    29. End If
    30. Next
    31. Next
    32. Return True
    33. End Function
    34. Public Shared Sub LogIn(ByVal Username As String, ByVal Password As String)
    35. AddAllowedChars()
    36. If Username.Length < 3 Then
    37. MsgBox("Der Benutzername ist zu kurz!" & ControlChars.CrLf & _
    38. "Es sind mindestens 3 und maximum 12 Zeichen erlaubt!", MsgBoxStyle.Critical, "Zu kurzer Benutzername")
    39. Exit Sub
    40. End If
    41. If Password.Length < 6 Then
    42. MsgBox("Das Kennwort ist zu kurz!" & ControlChars.CrLf & _
    43. "Es sind mindestens 6 und maximum 24 Zeichen erlaubt!", MsgBoxStyle.Critical, "Zu kurzes Kennwort")
    44. Exit Sub
    45. End If
    46. If CheckAccInfoIsOk(Username) = False Then
    47. MsgBox("Der Benutzername enthält verbotene Zeichen." & ControlChars.CrLf & _
    48. "Es sind nur A-Z, a-z, 0-9 und _ erlaubt!", MsgBoxStyle.Critical, "Verbotener Benutzername")
    49. Exit Sub
    50. ElseIf Username.Contains("@") Or Username.Contains(".") Then
    51. MsgBox("Der Benutzername enthält verbotene Zeichen." & ControlChars.CrLf & _
    52. "Es sind nur A-Z, a-z, 0-9 und _ erlaubt!", MsgBoxStyle.Critical, "Verbotener Benutzername")
    53. Exit Sub
    54. End If
    55. If CheckAccInfoIsOk(Password) = False Then
    56. MsgBox("Das Kennwort enthält verbotene Zeichen." & ControlChars.CrLf & _
    57. "Es sind nur A-Z, a-z, 0-9 und _ erlaubt!", MsgBoxStyle.Critical, "Verbotenes Kennwort")
    58. Exit Sub
    59. ElseIf Password.Contains("@") Or Password.Contains(".") Then
    60. MsgBox("Das Kennwort enthält verbotene Zeichen." & ControlChars.CrLf & _
    61. "Es sind nur A-Z, a-z, 0-9 und _ erlaubt!", MsgBoxStyle.Critical, "Verbotenes Kennwort")
    62. Exit Sub
    63. End If
    64. If Client.Connected = False Then
    65. Client.Connect(IP, Port)
    66. End If
    67. Dim Command As String = "CltLogin:<" & Username & ">[" & Password & "]"
    68. Client.SendMessage(Command)
    69. End Sub
    70. Public Shared Sub Registry(ByVal Username As String, ByVal Password As String, ByVal cPassword As String, ByVal EMail As String, ByVal cEmail As String)
    71. AddAllowedChars()
    72. If Username.Length < 3 Then
    73. MsgBox("Der Benutzername ist zu kurz!" & ControlChars.CrLf & _
    74. "Es sind mindestens 3 und maximum 12 Zeichen erlaubt!", MsgBoxStyle.Critical, "Zu kurzer Benutzername")
    75. Exit Sub
    76. End If
    77. If Password.Length < 6 Then
    78. MsgBox("Das Kennwort ist zu kurz!" & ControlChars.CrLf & _
    79. "Es sind mindestens 6 und maximum 24 Zeichen erlaubt!", MsgBoxStyle.Critical, "Zu kurzes Kennwort")
    80. Exit Sub
    81. End If
    82. If Not EMail.Contains("@") Or Not EMail.Contains(".") Then
    83. MsgBox("Die E-Mail Adresse ist unvolstendig!", MsgBoxStyle.Critical, "Ungültige E-Mail Adresse")
    84. Exit Sub
    85. End If
    86. If CheckAccInfoIsOk(Username) = False Then
    87. MsgBox("Der Benutzername enthält verbotene Zeichen." & ControlChars.CrLf & _
    88. "Es sind nur A-Z, a-z, 0-9 und _ erlaubt!", MsgBoxStyle.Critical, "Verbotener Benutzername")
    89. Exit Sub
    90. ElseIf Username.Contains("@") Or Username.Contains(".") Then
    91. MsgBox("Der Benutzername enthält verbotene Zeichen." & ControlChars.CrLf & _
    92. "Es sind nur A-Z, a-z, 0-9 und _ erlaubt!", MsgBoxStyle.Critical, "Verbotener Benutzername")
    93. Exit Sub
    94. End If
    95. If CheckAccInfoIsOk(Password) = False Then
    96. MsgBox("Das Kennwort enthält verbotene Zeichen." & ControlChars.CrLf & _
    97. "Es sind nur A-Z, a-z, 0-9 und _ erlaubt!", MsgBoxStyle.Critical, "Verbotenes Kennwort")
    98. Exit Sub
    99. ElseIf Password.Contains("@") Or Password.Contains(".") Then
    100. MsgBox("Das Kennwort enthält verbotene Zeichen." & ControlChars.CrLf & _
    101. "Es sind nur A-Z, a-z, 0-9 und _ erlaubt!", MsgBoxStyle.Critical, "Verbotenes Kennwort")
    102. Exit Sub
    103. End If
    104. If CheckAccInfoIsOk(EMail) = False Then
    105. MsgBox("Die E-Mail Adresse enthält verbotene Zeichen." & ControlChars.CrLf & _
    106. "Es sind nur A-Z, a-z, 0-9 und _ erlaubt!", MsgBoxStyle.Critical, "Ungültige E-Mail")
    107. Exit Sub
    108. End If
    109. If Not Password = cPassword Then
    110. MsgBox("Die Kennwörter stimmen nicht überein!", MsgBoxStyle.Critical, "Unterschiedliche Kennwörter")
    111. Exit Sub
    112. End If
    113. If Not EMail = cEmail Then
    114. MsgBox("Die E-Mail Adressen stimmen nicht überein!", MsgBoxStyle.Critical, "Unterschiedliche E-Mail's")
    115. Exit Sub
    116. End If
    117. If Client.Connected = False Then
    118. Client.Connect(IP, Port)
    119. End If
    120. Dim Command As String = "CltRegistration:<" & Username & ">[" & Password & "]{" & EMail & "}"
    121. Client.SendMessage(Command)
    122. End Sub
    123. Public Shared Sub SendMessage(ByRef MessageInput As RichTextBox)
    124. Dim Message As String = User.Account.Username & ": " & MessageInput.Text
    125. MessageInput.SelectAll()
    126. MessageInput.Cut()
    127. Client.SendMessage(Message)
    128. End Sub
    129. End Class
    130. End Class



    Client Klasse
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports System.Net
    3. Imports System.Threading
    4. Imports System.Net.Sockets
    5. Public Class Client
    6. Private Shared clt As New TcpClient
    7. Private Shared stream As NetworkStream
    8. Private Shared stream_w As StreamWriter
    9. Private Shared stream_r As StreamReader
    10. Private Shared Listener As Thread
    11. Public Shared Property Connected As Boolean = False
    12. Private Shared Sub _reciver()
    13. While True
    14. Try
    15. Dim msg As String = stream_r.ReadLine
    16. DoCommand(msg)
    17. Catch ex As Exception
    18. DoCommand("Svr$disconnected$")
    19. End Try
    20. End While
    21. End Sub
    22. Public Shared Function Connect(ByVal IP As String, ByVal Port As Integer) As Boolean
    23. On Error GoTo fehler
    24. clt.Connect(IP, Port)
    25. Do Until clt.Connected
    26. Application.DoEvents()
    27. Loop
    28. stream = clt.GetStream
    29. stream_w = New StreamWriter(stream)
    30. stream_r = New StreamReader(stream)
    31. Listener = New Thread(AddressOf _reciver)
    32. Listener.IsBackground = True
    33. Listener.Start()
    34. Connected = clt.Connected
    35. Return True
    36. fehler:
    37. Connected = clt.Connected
    38. Return False
    39. End Function
    40. Public Shared Sub Disconnect()
    41. Dim msg As String = "CltDC:" & "#" & User.Account.ID & "$"
    42. SendMessage(msg)
    43. clt.Close()
    44. Connected = clt.Connected
    45. End Sub
    46. Public Shared Sub SendMessage(ByVal Message As String)
    47. Try
    48. stream_w.WriteLine(Message)
    49. stream_w.Flush()
    50. Catch ex As Exception
    51. DoCommand("Svr$disconnected$")
    52. End Try
    53. End Sub
    54. Private Shared Sub DoCommand(ByVal msg As String)
    55. If msg = "Svr$disconnected$" Then
    56. MsgBox("Verbindung zum Server verloren!" & ControlChars.CrLf & _
    57. "Das Progtamm wird geschloßen!", MsgBoxStyle.Critical, "Fehler")
    58. Application.Exit()
    59. ElseIf msg.StartsWith("SvrLogin:") Then
    60. Dim Answer As SByte = Filter.GetAnswerID(msg)
    61. If Answer = Login.Complete Then
    62. User.Account.Username = Filter.GetUsername(msg)
    63. User.Account.Password = Filter.GetPassword(msg)
    64. User.Account.EMail = Filter.GetEMail(msg)
    65. User.Account.ID = Filter.GetID(msg)
    66. ChatRoom.Show()
    67. MsgBox("Anmeldung erfolgreich!", MsgBoxStyle.Information, "Angemeldet")
    68. ElseIf Answer = Login.UserNotFound Then
    69. MsgBox("Dieser Benutzername exestiert nicht!", MsgBoxStyle.Critical, "Falscher Benutzername")
    70. ElseIf Answer = Login.IncorrectPassword Then
    71. MsgBox("Das Kennwort ist falsch!", MsgBoxStyle.Critical, "Falsches Kennwort")
    72. ElseIf Answer = Login.UserIsBanned Then
    73. MsgBox("Dieser Benutzername ist gebannt!", MsgBoxStyle.Critical, "Benutzername gebannt")
    74. End If
    75. ElseIf msg.StartsWith("SvrRegistration:") Then
    76. Dim Answer As SByte = Filter.GetAnswerID(msg)
    77. If Answer = Registration.Complete Then
    78. MsgBox("Die Registration war erfolgreich!", MsgBoxStyle.Information, "Registration abgeschlossen")
    79. User.Account.Username = Filter.GetUsername(msg)
    80. User.Account.Password = Filter.GetPassword(msg)
    81. User.Account.EMail = Filter.GetEMail(msg)
    82. User.Account.ID = Filter.GetID(msg)
    83. msg = ""
    84. ChatRoom.Show()
    85. frmRegistrations.Close()
    86. ElseIf Answer = Registration.UserExists Then
    87. MsgBox("Der gewählte Benutzername exestiert bereits!", MsgBoxStyle.Critical, "Benutzername vergeben")
    88. End If
    89. End If
    90. End Sub
    91. End Class



    Filter Klasse
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Filter
    2. Public Shared Sub SelectTextRegion(ByVal rtf As RichTextBox, ByVal FirstChar As String, ByVal SecondChar As String)
    3. Dim FindFirstPosition As Integer = rtf.Text.IndexOf(FirstChar, _
    4. rtf.SelectionStart + rtf.SelectionLength)
    5. If FindFirstPosition = -1 Then
    6. FindFirstPosition = rtf.Text.IndexOf(FirstChar)
    7. End If
    8. If FindFirstPosition <> -1 Then
    9. Dim FindSecondPosition As Integer = rtf.Text.IndexOf(SecondChar, _
    10. FindFirstPosition)
    11. If FindSecondPosition <> -1 Then
    12. rtf.SelectionStart = FindFirstPosition
    13. rtf.SelectionLength = (FindSecondPosition - FindFirstPosition) + 1
    14. rtf.Focus()
    15. End If
    16. End If
    17. End Sub
    18. Public Shared Function GetUsername(ByVal RequestLine As String) As String
    19. Dim rtb As New RichTextBox With {.Text = RequestLine}
    20. Call SelectTextRegion(rtb, "<", ">")
    21. rtb.Cut()
    22. rtb.SelectAll()
    23. rtb.Paste()
    24. Dim line As String = rtb.Text
    25. line = line.Remove(0, 1)
    26. Return line.Remove(line.Length - 1, 1)
    27. End Function
    28. Public Shared Function GetPassword(ByVal RequestLine As String) As String
    29. Dim rtb As New RichTextBox With {.Text = RequestLine}
    30. Call SelectTextRegion(rtb, "[", "]")
    31. rtb.Cut()
    32. rtb.SelectAll()
    33. rtb.Paste()
    34. Dim line As String = rtb.Text
    35. line = line.Remove(0, 1)
    36. Return line.Remove(line.Length - 1, 1)
    37. End Function
    38. Public Shared Function GetEMail(ByVal RequestLine As String) As String
    39. Dim rtb As New RichTextBox With {.Text = RequestLine}
    40. Call SelectTextRegion(rtb, "{", "}")
    41. rtb.Cut()
    42. rtb.SelectAll()
    43. rtb.Paste()
    44. Dim line As String = rtb.Text
    45. line = line.Remove(0, 1)
    46. Return line.Remove(line.Length - 1, 1)
    47. End Function
    48. Public Shared Function GetAnswerID(ByVal msg As String) As SByte
    49. Dim rtb As New RichTextBox With {.Text = msg}
    50. Call SelectTextRegion(rtb, "`", "´")
    51. rtb.Cut()
    52. rtb.SelectAll()
    53. rtb.Paste()
    54. Dim line As String = rtb.Text
    55. line = line.Remove(0, 1)
    56. Return line.Remove(line.Length - 1, 1)
    57. End Function
    58. Public Shared Function GetID(ByVal msg As String) As UInteger
    59. Dim rtb As New RichTextBox With {.Text = msg}
    60. Call SelectTextRegion(rtb, "#", "$")
    61. rtb.Cut()
    62. rtb.SelectAll()
    63. rtb.Paste()
    64. Dim line As String = rtb.Text
    65. line = line.Remove(0, 1)
    66. Return line.Remove(line.Length - 1, 1)
    67. End Function
    68. End Class



    Enums
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Module Enums
    2. Public Enum Login As SByte
    3. Complete = 0
    4. UserNotFound = 1
    5. IncorrectPassword = 2
    6. UserIsBanned = 4
    7. End Enum
    8. Public Enum Registration As SByte
    9. Complete = 0
    10. UserExists = 1
    11. End Enum
    12. End Module



    Ich kann bei Bedarf die ganze Projectmappe hochladen und hier den Link posten.

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

    dann wäre denke ich der Code der Formulare nicht schlecht, bzw. gleich das gesamte Projekt, denn ich komm sonst auf nichts, was das aufhalten könnte... :P
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Die Projectmappe

    Habe der Projectmappe auch noch einen Server beigelegt, den Server habe ich früher mal zum ausprobieren geschrieben udn jetzt eignet der sich gut zu Testzwecken^^.
    Die Protokollantworten müssen aber manuell geschrieben werden.

    Antwort vom Server zum Client für:
    Login: SvrLogin:`nr1´<username>[password]{email}#id$
    Registration: SvrRegistration:`nr2´<username>[password]{email}#id$

    id ist einfach nur eine Nummer die dem Client vom Server zugeteilt wird.
    nr1 siehe Login Enum
    nr2 siehe Registration Enum

    VB.NET-Quellcode

    1. Public Enum Login As SByte
    2. Complete = 0
    3. UserNotFound = 1
    4. IncorrectPassword = 2
    5. UserIsBanned = 4
    6. End Enum
    7. Public Enum Registration As SByte
    8. Complete = 0
    9. UserExists = 1
    10. End Enum


    Die Mappen sind aber für VS2010

    Wen du keins hast, dann sprich mich über PN an^^
    Grund für dieses Problem gefunden und somit wurde das Problem behoben.

    Grund:
    Steuerelemente wie z.B. eine TextBox, Form oder Label dürfen nicht in einem Thread Sub vorkommen. Ich weiß zwar nicht mit wahrscheinlicher Sicherheit wieso, aber es ist so^^.

    Lösung:
    Eine Variable und einen Timer einbauen. Sobald ein Vorgang mit den Steuerelementen gemachtw erden soll, wird diese Variable auf True gesetzt. Der Timer überprüft, ob sie True ist und macht den gewünschten Vorgang.
    das ist Threadübergreifend und verboten(es gibt CheckForIllegalCrossThreads...oder soetwas, ist aber nicht zu empfehlen...)eine bessere Lösung wäre ein Delegate welcher eine Methode aufruft, welche im GUI Thread läuft...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    VB.NET-Quellcode

    1. Private Sub Delegate DieFunktionDel()
    2. Sub DieFunktion()
    3. If Me.InvokeRequired Then
    4. Me.Invoke(New DieFunktionDel(AddressOf DieFunktion))
    5. Else
    6. 'der auszuführende Code, bei welchem auf die GUI zugegriffen werden soll...
    7. End If
    8. 'Methode des Threads:
    9. While...'mach irgendetwas...
    10. 'ändere Controls:
    11. DieFunktion()


    ich hoffe das hilft dir ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---