VersuchsChat mit leistungsfähigem Server

    • VB.NET

    Es gibt 80 Antworten in diesem Thema. Der letzte Beitrag () ist von n1nja.

      Die Basis Klassen nerven, die am besten gegen ein Interface austauschen. Oder ganz Weg damit, genau wie diese GUI Invoke (Server haben keine GUI zu haben, sie sind endweder CMD,s oder Dienste!).

      BTTT (Back to the Topic):
      Für mich ist es tatsächlich so einfach, ich bin aber ja auch Hacker.

      LG, Herbrich
      Könnte man da eigentlich ein Token für Stillalive einbauen?

      Wenn ja, wie würde man das am besten machen?
      So , dass der Server einen Timer hat und nach bestimmten Intervallen eine Nachricht an die Clients sendet?

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

      Wie bekomme ich das Invoke für dne GUI Thread weg?? Ser Server läuft als Dienst oder CMD bei mir :)
      ErfinderDesRades

      Habe Frage an dich:

      Und zwar füge ich die Clients einem ListView Item hinzu.

      Jetzt würde ich diese Clients natürlich gerne auch wieder löschen, wenn
      sie disposed werden.

      Folgendes habe ich probiert:(Codeausschnitte)
      'HelperClazz.GetAllClients liefert alle Clients vom Typ EasyClient (der TCPClient ist ein und derselbe wie aus der AllClientz Liste)

      VB.NET-Quellcode

      1. Private Sub _ServerOrClient_IndividRemove(sender As Object, e As NotifyEventArgs(Of TcpClient)) Handles _ServerOrClient.IndividRemove
      2. Throw New Exception("YEAH")
      3. Dim t As String = (IPAddress.Parse(CType(e.Value.Client.RemoteEndPoint, IPEndPoint).Address.ToString())).ToString
      4. Me.Text = t
      5. End Sub


      VB.NET-Quellcode

      1. Public MustInherit Class TCPBase : Implements IDisposable
      2. Private _IsDisposed As Boolean = False
      3. Public Event Disposed As EventHandlerEx(Of TCPBase)
      4. Protected MustOverride Sub Dispose(disposing As Boolean)
      5. Public MustOverride Sub Send(Msg As String)
      6. Public MustOverride Sub Send(Msg As Byte)
      7. Public Event StatusMessage As EventHandler(Of NotifyEventArgs(Of String))
      8. Public Event IndividRemove As EventHandler(Of NotifyEventArgs(Of TcpClient))
      9. Protected Sub IndividRe(se As TcpClient)
      10. RaiseEvent IndividRemove(Me, New NotifyEventArgs(Of TcpClient)(se))
      11. End Sub


      VB.NET-Quellcode

      1. #Region "_Clients-Ereignisverarbeitung"
      2. Private Sub Client_Disposed(Sender As TCPBase)
      3. 'den Client für die beendete Verbindung entfernen
      4. IndividRe(HelperClazz.GetAllClients.ToList.SingleOrDefault(Function(w) w.Equals(Sender)).TC)
      5. Sender.RemoveFrom(AllClientz)
      6. Sender.RemoveFrom(HelperClazz.AllClient)
      7. End Sub
      8. #End Region


      Kannst Du mir dazu etwas hilfe geben?
      "Sender.RemoveFrom(AllClientz)
      Sender.RemoveFrom(HelperClazz.AllClient)"

      Bitte nicht!

      Da ich bei deinem Code grade nicht so dürchblicke kann ich dir leider nicht helfen.

      MfG

      Edit: Wieso überhaupt ein Listview ? Verwende doch ein Datagridview, pracktisch die Liste vom Server direkt mit dem Control verbinden, dann wird der Client beim Disposen automatisch ausm GUI entfernt.

      Edit1: Da war wohl Jemand schneller ^^

      Die Farbe "Rot" ist der Moderation vorbehalten -> Farbe geändert. ~Thunderbolt

      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „schockerjo“ ()

      Das ist klar..

      Ich bin jetzt ein Stück weiter gekommen, aber irgendwas scheitert am Event Raise.

      In TCPBase habe ich Folgendes:

      VB.NET-Quellcode

      1. Public Class NotifyEventArgs(Of T) : Inherits EventArgs
      2. Public ReadOnly Value As T
      3. Public Sub New(Value As T)
      4. MyBase.New()
      5. Me.Value = Value
      6. End Sub
      7. End Class
      8. Public Event IndividRemove As EventHandler(Of NotifyEventArgs(Of TcpClient))
      9. Protected Sub IndividRe(se As TcpClient)
      10. Throw New Exception("yeah")
      11. RaiseEvent IndividRemove(Me, New NotifyEventArgs(Of TcpClient)(se))
      12. End Sub


      EndRead sieht wie folgt aus:


      VB.NET-Quellcode

      1. Private Sub EndRead(ar As IAsyncResult)
      2. If MyBase.IsDisposed Then Return
      3. Try
      4. If Not TC.Connected Then
      5. CrossThread.RunGui(AddressOf IndividRe, TC)
      6. CrossThread.RunGui(AddressOf OnConnectionLost)
      7. CrossThread.RunGui(AddressOf OnStatusMessage, Ste.Enc("CounterClient shut down"))
      8. CrossThread.RunGui(AddressOf MyBase.Dispose)
      9. Exit Sub
      10. End If
      11. Dim msg As String = RSt.EndInvoke(ar)
      12. CrossThread.RunGui(AddressOf OnChatMessage, msg)
      13. RSt.BeginInvoke(AddressOf EndRead, Nothing) 'asynchrone Rekursion
      14. Catch ex As EndOfStreamException
      15. CrossThread.RunGui(AddressOf OnStatusMessage, Ste.Enc("CounterClient shut down"))
      16. CrossThread.RunGui(AddressOf MyBase.Dispose)
      17. End Try
      18. End Sub


      Empfangen:

      VB.NET-Quellcode

      1. Private Sub _ServerOrClient_IndividRemove(sender As Object, e As NotifyEventArgs(Of TcpClient)) Handles _ServerOrClient.IndividRemove
      2. Throw New Exception("received!")
      3. Dim t As String = (IPAddress.Parse(CType(e.Value.Client.RemoteEndPoint, IPEndPoint).Address.ToString())).ToString
      4. End Sub



      Das "yeah" wird mir ausgegeben , das "receive" dagegen nicht,
      was de facto heißt -> Der Protected Sub IndividRe wird zwar aufgerufen,
      aber die darin enthaltene Codezeile

      VB.NET-Quellcode

      1. RaiseEvent IndividRemove(Me, New NotifyEventArgs(Of TcpClient)(se))

      scheitert.

      Kann mir dazu jemand was sagen?

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Daniel Baumert“ ()

      Ich habs mit einem Client und einem Server getestet
      und die Sache ist ja (Bezug auf Protected Sub IndividRe) : "yeah" wird mir ausgegeben
      und ich habe auch "se" geprüft -> alles ok.

      VB.NET-Quellcode

      1. Private Sub _ServerOrClient_IndividRemove(sender As Object, e As NotifyEventArgs(Of TcpClient)) Handles _ServerOrClient.IndividRemov


      Das Event wird gar nicht erst ausgelöst!

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

      Daniel Baumert schrieb:

      Ich habs mit einem Client und einem Server getestet
      Das ändert nix daran, dass im Server-Objekt eine Liste von Client-Objekten ist.
      Zeig mal den Code, wie du deren RemoveIndiv-Event behandelst.

      Falls du nur mit einem Client testest ist in der Liste eben nur ein Client-Objekt drin.
      Meinst Du das?

      VB.NET-Quellcode

      1. Private Sub _ServerOrClient_IndividRemove(sender As Object, e As NotifyEventArgs(Of TcpClient)) Handles _ServerOrClient.IndividRemove
      2. 'Throw New Exception("received!")
      3. Dim t As String = (IPAddress.Parse(CType(e.Value.Client.RemoteEndPoint, IPEndPoint).Address.ToString())).ToString
      4. ListBox1.Items.Add(t)
      5. End Sub
      Das hier:

      VB.NET-Quellcode

      1. Public Event IndividRemove As EventHandler(Of NotifyEventArgs(Of TcpClient))
      2. Protected Sub IndividRe(se As TcpClient)
      3. Throw New Exception("yeah")
      4. RaiseEvent IndividRemove(Me, New NotifyEventArgs(Of TcpClient)(se))
      5. End Sub


      Habe ich in der TCPBase Klasse.



      Und das hier in der Client Klasse:

      VB.NET-Quellcode

      1. Private Sub _ServerOrClient_IndividRemove(sender As Object, e As NotifyEventArgs(Of TcpClient)) Handles _ServerOrClient.IndividRemove
      2. 'Throw New Exception("received!")
      3. Dim t As String = (IPAddress.Parse(CType(e.Value.Client.RemoteEndPoint, IPEndPoint).Address.ToString())).ToString
      4. ListBox1.Items.Add(t)
      5. End Sub





      Hab auch Folgendes probiert:

      VB.NET-Quellcode

      1. Public Event IndividRemove As EventHandlerEx(Of TcpClient)
      2. Protected Sub IndividRe(se As TcpClient)
      3. Throw New Exception("step 1 ok")
      4. RaiseEvent IndividRemove(se)
      5. End Sub


      Da wird mir auch "step 1 ok" angezeigt, auch "se" ist richtig , aber das Event
      IndividRemove wird nicht ausgelöst.

      Ist das so nicht korrekt?
      Der Server stellt doch grundlegend auch einen Client dar, nur dass er halt nebenbei noch
      andere Clients annehmen kann und somit Server ist.

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Daniel Baumert“ ()

      Du kannst in der Client-Klasse, und auch in der Tcp-Klasse und sonstwo - kannst du dich auf den Kopf stellen und mitte Zehen wackeln.
      Wenn du im Server die Client-Events nicht behandelst, dann werden die Client-Events der Clients im Server halt nicht behandelt

      Daniel Baumert schrieb:

      Der Server stellt doch grundlegend auch einen Client dar, nur dass er halt nebenbei noch
      andere Clients annehmen kann und somit Server ist.
      Der Server ist kein Client.
      Der Server ist im Wesentlichen ein TcpListener und eine Auflistung von Clients.

      Ich habe dich jetzt 4 mal auf den Server hingewiesen - wie oft möchtest du's noch hören?
      Ich habs doch jetzt auch schon paar Mal geschrieben...

      Die Sache ist: ich habe einen Client gehabt und als der sich disconnected hat,
      wurde Protected Sub IndividRe(se As TcpClient) doch aufgerufen!!!
      ALSO KLAPPT DAS DOCH.

      Das Einzige was nicht klappt, ist die Weiterleitung an das Event , das
      im SELBEN SUB aufgerufen wird.

      VB.NET-Quellcode

      1. Public Class Server : Inherits TCPBase
      2. Private ListNa As TcpListener
      3. Private AllClientz As New List(Of Client)
      4. Public Sub New(EP As IPEndPoint)
      5. ListNa = New TcpListener(EP) With {.ExclusiveAddressUse = False}
      6. ListNa.Start()
      7. ListNa.BeginAcceptTcpClient(AddressOf EndAccept, Nothing)
      8. End Sub
      9. Private Sub EndAccept(ar As IAsyncResult)
      10. If MyBase.IsDisposed Then Return
      11. With New Client(ListNa.EndAcceptTcpClient(ar))
      12. AddHandler .ChatMessage, AddressOf Client_ChatMessage
      13. AddHandler .StatusMessage, AddressOf Client_StatusMessage
      14. AddHandler .Disposed, AddressOf Client_Disposed
      15. .AddTo(AllClientz)
      16. .AddTo(HelperClazz.AllClient)
      17. End With
      18. CrossThread.RunGui(AddressOf OnStatusMessage, Ste.Enc("TCPClient accepted"))
      19. ListNa.BeginAcceptTcpClient(AddressOf EndAccept, Nothing)
      20. End Sub
      21. #Region "_Clients-Ereignisverarbeitung"
      22. Private Sub Client_Disposed(Sender As TCPBase)
      23. 'den Client für die beendete Verbindung entfernen
      24. Sender.RemoveFrom(AllClientz)
      25. Sender.RemoveFrom(HelperClazz.AllClient)
      26. End Sub
      27. Private Sub Client_ChatMessage(sender As Object, e As NotifyEventArgs(Of String))
      28. 'Send(e.Value) Bei einem Client ankommende ChatMessages anzeigen und an alle anderen Clients senden
      29. OnStatusMessage(e.Value)
      30. End Sub
      31. Private Sub Client_StatusMessage(sender As Object, e As NotifyEventArgs(Of String))
      32. 'einkommende StatusMessages durchreichen (zur Anzeige)
      33. OnStatusMessage(e.Value)
      34. End Sub
      35. #End Region
      36. Public Overrides Sub Send(Msg As String)
      37. 'OnChatMessage(Msg) ' Server soll Eigene Nachrichten anzeigen
      38. Parallel.ForEach(AllClientz, Sub(w As Client) w.Send(Msg))
      39. End Sub
      40. Public Overrides Sub Send(Msg As Byte)
      41. 'OnChatMessage(Msg) ' Server soll Eigene Nachrichten anzeigen
      42. Parallel.ForEach(AllClientz, Sub(w As Client) w.Send(Msg))
      43. End Sub
      44. Protected Overrides Sub Dispose(disposing As Boolean)
      45. ListNa.Stop()
      46. For i As Integer = AllClientz.Count - 1 To 0 Step -1
      47. AllClientz(i).Dispose()
      48. Next
      49. End Sub
      50. End Class


      Ich benötige ein Event, dass ich in Public Class Form1 (also der Klasse von der WinForm) nutzen kann.
      Dieses Event soll den TCPClient enthalten.

      Dann sag mir doch bitte, wie man das konkret umsetzen kann.
      Es soll dann ausgelöst werden, wenn ein Client disposed wird.