ReadTimeOut beim VersuchsChat von EDR

  • VB.NET

Es gibt 29 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    ReadTimeOut beim VersuchsChat von EDR

    Bezug: [VB.NET] VersuchsChat mit leistungsfähigem Server

    Hallo Zusammen,

    ich habe noch ein kleines Problem mit dem VersuchsChat vom ErfinderdesRad...
    Ich habe festgestellt - wenn mehrere Clients an den Server verbunden sind (ca. 200) - dann verliert manchmal ein Client übers Internet die Verbindung. Eine Sekunde später verbindet sich der Client sofort wieder.
    Ich habe bereits ein ReadTimeout auf 5000ms gesetzt, aber bei der asynchronen Methode zieht dieser ja nicht.

    Wie kann ich jetzt in dem Block einen ReadTimeout setzen, damit mir die
    "if read=0" - Funktion nicht sofort den Client killt. ??? ?(


    VB.NET-Quellcode

    1. Private Sub EndRead(ByVal ar As IAsyncResult) If MyBase.IsDisposed Then Return
    2. Dim read As Integer = _Stream.EndRead(ar)
    3. If read = 0 Then 'leere Datenübermittlung signalisiert Verbindungsabbruch
    4. CrossThread.RunGui(AddressOf OnStatusMessage, New MessageEventargs("CounterClient shut down"))
    5. CrossThread.RunGui(AddressOf MyBase.Dispose)
    6. Return
    7. End If
    8. Dim SB As New StringBuilder(Encoding.UTF8.GetString(Buf, 0, read))
    9. Do While _Stream.DataAvailable
    10. read = _Stream.Read(Buf, 0, Buf.Length)
    11. SB.Append(Encoding.UTF8.GetString(Buf, 0, read))
    12. Loop
    13. CrossThread.RunGui(AddressOf OnChatMessage, New MessageEventargs(SB.ToString))
    14. _Stream.BeginRead(Buf, 0, Buf.Length, AddressOf EndRead, Nothing)
    15. End Sub



    Danke schonmal im Voraus...

    Viele Grüsse...

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

    EntU schrieb:

    VB.NET-Quellcode

    1. Dim read As Integer = _Stream.EndRead(ar)
    2. If read = 0 Then 'leere Datenübermittlung signalisiert Verbindungsabbruch
    Oh - sollte ich mich mit der Annahme im Kommentar getäuscht haben?
    wäre vlt. problematisch, denn dann wüsste ich überhaupt kein Mittel, wie man eine Verbindung beenden kann.

    Derzeit funzt das so, dass wenn eine Seite schließt, als letztes noch sone Leer-Nachricht ans Gegenüber gesendet wird - das habe ich durch Rumprobieren rausgefunden. Wenn null-Nachrichten aber auch anderweitig auftreten, dann ist Null-Nachricht als CloseRequest-Indikator leider nicht verwendbar.

    vlt. hat ein Tcp-Sample ohne Protokoll einfach prinzipiell keinen Sinn.
    Also es muß ein Befehls-Protokoll her, und einer der Befehle muß "close" bedeuten, und ein Client, der schließen will, muß zuvor diesen Befehl senden.

    ErfinderDesRades schrieb:

    vlt. hat ein Tcp-Sample ohne Protokoll einfach prinzipiell keinen Sinn.
    Also es muß ein Befehls-Protokoll her, und einer der Befehle muß "close" bedeuten, und ein Client, der schließen will, muß zuvor diesen Befehl senden.
    Das mit dem Protokoll ist schon richtig und da unterstütze ich auch Deine Meinung. Aber was passiert, wenn die Verbindung völlig unerwartet abbricht ?
    Es muss doch irgendwie eine Möglichkeit geben, dann auf eine Exception oder dergleichen reagieren zu können. Ansonsten hätte man ja einige "tote" Verbindungen...

    ?(
    keine Ahnung.
    "Tote Verbindung" ist was, wassich nicht so einfach reproduzieren kann.
    Hat glaub 2 unerwünschte Eigenschaften:
    1) eine "stille" tote Verbindung belegt unnütze Resourcen
    2) wenn sie benutzt wird, gibts einen Fehler

    Das mit dem Fehler ist sicher eine Sache von ExceptionHandling, wobei ich nicht weiß, obs noch annere Exceptions als TimeOutException gibt.
    das mit den unnützen Resourcen - iwo habich mal aufgeschnappt, wie einer alle paar Sekunden eine "IsAlive"- Message gesendet hat. Aber ich weiß nichtmal, ob das Tcp war, oder ein primitiveres Übertragungsprotokoll. Und ich weiß nicht, ob die IsAlive-Geschichte nicht sogar in Tcp enthalten ist, sodaß man sich nicht drum kümmern muß, wennman TcpClients verwendet.

    gugge (und abonniere) auch diese Thread: [Allgemein] Tcp Client Event

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

    msdn.microsoft.com/de-de/libra…kets.socketexception.aspx

    Diese hier könnte auch geworfen werden, wenn das OS selbst bereits weiß, dass die Zugrundeliegende Verbindung geschlossen wurde, dann wär ein Timeout ja blödsinn, wenn ichs noch richtig weiß, wird dann eben diese geworfen.

    Richtig, TCP kümmert sich selbst um den Erhalt der Verbindung, sollte dies mal nicht möglich sein, so bekommt man das auch von TCP mitgeteilt. Hier muss man nichts mehr selbst implementieren ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Habe gerade mal bissl auf Msdn herumgeschnüffelt und habe das hier entdeckt: Link
    "returns -1 if at the end of the stream"
    Also dacht ich mir, mach ich einfach so was hier ^^

    VB.NET-Quellcode

    1. While Not NewTcpClient.GetStream.ReadByte = -1
    2. NewStreamWriter.Write("test")
    3. NewStreamWriter.Flush()
    4. End While
    5. MessageBox.Show("Client hat die Verbindung abgebrochen")

    Julius schrieb:

    VB.NET-Quellcode

    1. While Not NewTcpClient.GetStream.ReadByte = -1
    2. ' ...
    3. End While
    Und nun noch richtig lesbar:

    VB.NET-Quellcode

    1. Do Until NewTcpClient.GetStream.ReadByte = -1
    2. ' ...
    3. Loop
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Julius: schön und gut, funktioniert, aber warum sollte jemand einzelne Bytes lesen? nehm die Normale Read-Methoden(oder auch Async), diese geben dann einfach 0 zurück. Du musst auch wenn du Bytes einzeln ausliest Exceptions fangen ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    jvbsl schrieb:


    @Julius: schön und gut, funktioniert, aber warum sollte jemand einzelne Bytes lesen? nehm die Normale Read-Methoden(oder auch Async), diese geben dann einfach 0 zurück. Du musst auch wenn du Bytes einzeln ausliest Exceptions fangen
    Also sehe ich das richtig, das ich lieber statt auf die 0 zu reagieren eher auf eine Exception reagieren sollte ?
    Also nicht

    VB.NET-Quellcode

    1. if read=0
    2. ...
    3. end if


    sondern lieber

    VB.NET-Quellcode

    1. Try
    2. read = _Stream.EndRead(ar)
    3. Catch ex As Exception
    4. CrossThread.RunGui(AddressOf MyBase.Dispose) ' Verbindung trennen
    5. End Try




    ????
    ?( :?: :?: ?(
    Nein.
    Du hattest aber oben Code mit ReadByte =-1...Das sollte man lassen.
    Du solltest auf Exceptions UND read = 0 (der Read bzw EndRead Funktionen) reagieren. Denn es kann auch neue Exception kommen, das ist mehr oder weniger Zufall.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    jvbsl schrieb:


    Nein.
    Du hattest aber oben Code mit ReadByte =-1...Das sollte man lassen.
    Du solltest auf Exceptions UND read = 0 (der Read bzw EndRead Funktionen) reagieren. Denn es kann auch neue Exception kommen, das ist mehr oder weniger Zufall.
    Also dann so ?

    VB.NET-Quellcode

    1. Dim read As Integer
    2. Try
    3. _Stream.EndRead(ar)
    4. Catch
    5. read = 0
    6. End Try
    7. If read = 0 Then 'leere Datenübermittlung signalisiert Verbindungsabbruch
    8. CrossThread.RunGui(AddressOf OnStatusMessage, New MessageEventargs("CounterClient shut down"))
    9. CrossThread.RunGui(AddressOf MyBase.Dispose)
    10. Return
    11. End If

    VB.NET-Quellcode

    1. Try
    2. read=_Streams.EndRead(...)
    3. Catch Ioexception'evtl. Noch ObjectDisposedException
    4. read=0
    5. End Try
    6. ...

    Eher so. Denn Du hast ja mit deinem wieder nur Exceptions UND fängst auch noch alle. Man sollte immer spezifische Exceptions fangen un später Fehler zu vermeiden und kompliziertes debugging ebenfalls....
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    So habe jetzt mal bissl rumgetestet.

    StreamReader.Read = 0 ist aus meiner Sicht völliger Schwachsinn, wieso ? Wenn man den Stream einfach mal die ganze Zeit über ausgibt, erhält man folgendes:

    Beispielaufbau:

    VB.NET-Quellcode

    1. Private Sub ListenToArrivedConnection(ByVal Connection As Player)
    2. While True
    3. MessageBox.Show(Connection.StreamReader.Read.ToString)
    4. End While
    5. End Sub


    Sobald der Client beendet wird, wird der Wert -1 zurückgegeben ->Fazit: Client nicht erreichbar !
    Jedoch würde ich gerne noch wissen, wieso ihr euch oben gegen meine Methode gesträubt habt. Die "Stream.ReadByte Function" ist doch genau für das da und wenn man sich die Exceptions anguckt, welche kommen können, wenn man diese Function anwendet, dann wird man sehen, dass die einzig relevante "ObjectDisposedException", welche man aber sicher nicht erhält, wenn der Code stimmt.

    Julius schrieb:

    Eure Meinungen, zum oberen Beitrag, sind immer noch gerne zu sehen =)
    Hallo Julius,

    Sorry, die verspätete Rückmeldung...
    Bei mir findet das ganze noch keine Beachtung, da ich ja asynchron lese. Also mit .BeginRead und .EndRead arbeite.
    Deine vorgeschlagene Methode ist aber nur das normale .Read oder .ReadByte

    Aber vielleicht liege ich da auch völlig falsch...
    @Julius:
    Deine Methode ist Quatsch, da du da nur einzelne Bytes liest, dadurch wird diese Methode zu lesen verdammt langsam. Außerdem kannst du dann keine Streams verwenden, wodurch du keine gescheite Architektur und auch kein gescheites Protokoll aufbauen kannst.

    Wenn du richtig programmierst, dann kann auch die ObjectDisposedException kommen, da du Asynchron arbeiten kannst und beim schließen disposed->Objekt disposed, obwohl du noch liest.
    Die Methode mit Exceptions+Read=0 funktioniert mit einem Puffer, dann mit Asynchronen sowie Synchronen Methoden. Perfekt für jegliche Art von Streams.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---