WebSocket Server

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Dadido3
Beiträge: 103
Registriert: 24.02.2007 22:15
Kontaktdaten:

Re: WebSocket Server

Beitrag von Dadido3 »

Ok, ich habe mal versucht eine schlechte Verbindung zu simulieren. Dabei habe ich gemerkt dass im Callback die falschen Frames zurückgegeben wurden, wenn viele Frames auf einmal reinkamen. Ältere Frames kamen doppelt vor, und neuere wurden "verschluckt".

Habe den Fehler jetzt behoben, hoffe mal dass das Problem bei dir nun gelöst ist. Es ist nur seltsam, weil es kein Betriebssystemspezifisches Problem war. Aber möglicherweise sind die Windows-Maschinen, welche du zum Testen genutzt hast, besser an das Netzwerk angebunden. Jetzt sollte es aber mit jeder Verbindung funktionieren.
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

Re: WebSocket Server

Beitrag von stevie1401 »

Ich denke ich habe den Fehler gefunden:
Ich habe das Senden und Empfangen etwas verändert (hab ich nicht erwähnt, weil ich dachte, das könnte nicht das Problem sein.)
Ich sende und empfange NICHT mehr mit JSON.
Ich sende Spiderseitig mit:


Procedure sende(message.s)
! websocket.send(v_message);
EndProcedure


Und ich verarbeite Serverseitig mit Purebasic NICHT mehr so:
JSON_ID = CatchJSON(#PB_Any, *Event_Frame\Payload, *Event_Frame\Payload_Size)

sondern so:

aString=PeekS(*Event_Frame\Payload, *Event_Frame\Payload_Size, #PB_UTF8)

Und genau DA war der Fehler.
RICHTIG scheint zu sein das Flag: #PB_ByteLength mit einzubauen

aString=PeekS(*Event_Frame\Payload, *Event_Frame\Payload_Size, #PB_UTF8|#PB_ByteLength)

Ich teste weiter, aber es sieht jetzt gut aus.

Vielen Dank für deine Mühen!
Und entschuldige bitte, dass ich das mit dem PeekS() nicht gesagt habe!
Dann hättest du den Fehler bestimmt sofort gefunden.
Aber es hat ja auch etwas Gutes, so hast du den (kleinen) Bug mit dem Doppelt-Senden gefunden. :)
Ich programmiere nur noch mit Linux.
Linux Mint 21.x
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

Re: WebSocket Server

Beitrag von stevie1401 »


http://www.doko-lounge.de/servererror.jpg


Ab und zu tritt dieser Fehler auf. Ich kann ihn leider nicht deuten.
Was bedeutet Speicherfehler und wie kommt das zustande? Wenn Clients eine Verbindung aufbauen oder diese lösen?
Ich programmiere nur noch mit Linux.
Linux Mint 21.x
Benutzeravatar
dige
Beiträge: 1182
Registriert: 08.09.2004 08:53

Re: WebSocket Server

Beitrag von dige »

Vermutlich gibt es *Object nicht mehr? Wenn der Fehler immer an dieser Stelle auftritt, würde ich den
Code mal umbauen und vor der NetworkServerEvent() Abfrage einen Check auf *Object integrieren.
"Papa, mein Wecker funktioniert nicht! Der weckert immer zu früh."
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

Re: WebSocket Server

Beitrag von stevie1401 »

Vielen Dank für den Tip!
Ich werde mal versuchen, ob ich das dann irgendwie abfangen kann, obwohl ich zugegebenermaßen keine Ahnung von dem habe, was da programmiert wurde.
Aber dein Tip hilft mir jedenfalls schon einmal weiter ;)
Ich programmiere nur noch mit Linux.
Linux Mint 21.x
Benutzeravatar
Dadido3
Beiträge: 103
Registriert: 24.02.2007 22:15
Kontaktdaten:

Re: WebSocket Server

Beitrag von Dadido3 »

*Object dürfte innerhalb des Threads nie ungültig werden, weil FreeStructure(*Object) erst (und nur) aufgerufen wird, wenn der Thread seine Hauptschleife beendet. Und das passiert nur beim Beenden des Servers.
Ich vermute, dass der Fehler von NetworkServerEvent stammt, aber auch hier wird der Server erst geschlossen, wenn der Thread aus der Hauptschleife geht. Leider kann ich nicht nachvollziehen, warum es da crashen könnte.

Tritt der fehler mitten im Betrieb auf, oder wenn der Server gestartet wird?
Wie sieht ungefähr deine Verwendung meiner Lib aus? Eventuell kannst du mit Pseudocode zeigen, wie du die events abfragst, und auf geschlossene clients reagierst.
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: WebSocket Server

Beitrag von mk-soft »

Ich weiss nicht genau an welchen Punkt.

Da die Network Funktionen auch mit Threads und Mutex arbeitet, hilft es bei Linux und macOS nach CloseNetworkServer / CloseNetworkConnection ein kleines Delay(1) einzusetzen, um ein Thread Wechsel zu erzwingen.

Ach ja ...

Das senden mit SendNetworkData oder SendNetworkString von einen anderen Thread auf einer nicht mehr vorhanden Connection Crash bei macOS.
Könnte bei Linux das gleiche seine. Bei Windows erhält man als Ergebnis "-1"
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

Re: WebSocket Server

Beitrag von stevie1401 »

An Dadido3:
Zur Zeit benutzen den Server ca 30-100 Clients gleichzeitig.
Der Crash trifft "irgendwann" auf, also nicht am Anfang.
"Gefühl" tritt das auf, wenn ein Client sich anmeldet und sofort wieder rausgeht. Belegen kann ich meine Vermutung nicht.

Der Server läuft mal auf Linux native, mal auf Linux unter WINE und mal auf Windows 10. (Einfach um mal alles zu testen)

Ich kann dir gerne meinen kompletten Servercode zukommen lassen, falls du Interesse hast, aber nur wenn du mir hoch und heilig versprichtst, nicht laut zu lachen, wenn meinen Code siehst ;)
Er wäre zu lang, ihn hier zu posten.
Ich programmiere nur noch mit Linux.
Linux Mint 21.x
Benutzeravatar
Dadido3
Beiträge: 103
Registriert: 24.02.2007 22:15
Kontaktdaten:

Re: WebSocket Server

Beitrag von Dadido3 »

mk-soft hat geschrieben:SendNetworkData oder SendNetworkString von einen anderen Thread auf einer nicht mehr vorhanden Connection Crash bei macOS
Der Server wird nur in einem einzelnen Thread verwaltet, es sollte eigentlich keine Probleme deswegen geben. Und das mit dem Delay(1) wäre seltsam und würde schon fast an einen Bug grenzen. Es stimmt schon, dass delay nen Contextwechsel an dieser stelle verursacht, aber das sollte nicht notwendig sein.
stevie1401 hat geschrieben:"Gefühl" tritt das auf, wenn ein Client sich anmeldet und sofort wieder rausgeht
Das ist doch schonmal ein Anhaltspunkt, es könnte sein, dass ich einen Fehler im handling beim Handshake hab (Oder bei verbindungsabbrüchen während dem Handshake). Oder es könnte sein, dass du das client handle weiterverwendest, obwohl ein #Event_Disconnect zurückgegeben wurde. Wichtig ist erstmal den Fehler schnell und wiederholbar reproduzieren zu können, wenn das irgendwie gelingt ist es relativ einfach das Problem einzugrenzen.
stevie1401 hat geschrieben:Der Server läuft mal auf Linux native, mal auf Linux unter WINE und mal auf Windows 10
Ich gehe davon aus, dass das Problem überall gleichermaßen auftritt, korrekt?
stevie1401 hat geschrieben:Ich kann dir gerne meinen kompletten Servercode zukommen lassen
Ich kann ja mal einen Blick drauf werfen, eventuell fällt mir was auf.
Benutzeravatar
Dadido3
Beiträge: 103
Registriert: 24.02.2007 22:15
Kontaktdaten:

Re: WebSocket Server

Beitrag von Dadido3 »

Ein kurzes Zwischenergebnis:

@stevie1401

Soweit ich es sehen konnte verwendet dein Code meine Lib korrekt. Es werden auch keine Threads genutzt, sodass es relativ einfach war dies zu überprüfen.

Ich glaube der Fehler liegt entweder in meiner Lib, bei PureBasic oder irgendwo dazwischen. Dazwischen würde bedeuten, dass ich die Netzwerkbefehle missverstehe, oder die Dokumentation fehlerhaft/unvollständig ist.

Ich hab jetzt ne kleine Testumgebung geschaffen, in der ich den Server mit Verbindungen und Verbindungsabbrüchen befeuere. Damit bekomme ich einen Crash alle paar Minuten bis halbe Stunde. Mit "Server" meine ich den reinen Websocket server, und das ohne Auswertung von Events.

Erkenntnisse:
  • Abstürze werden nur selten vom Debugger abgefangen, also das Executable beendet sich einfach so (Das ist unter Win 10, unter linux wird es wahscheinlich so wie bei dir abgefangen)
  • Wenn sie abgefangen werden, dann immer bei irgendwelchen Netzwerkbefehlen
  • Soweit ich sehen konnte gibt es keine Regelmäßigkeit (z.B. Crash nach Senden von x, Crash nach empfangen vom HTTP header)
  • Nach mehreren versuchen klappt der Versuchsaufbau nicht mehr, verbindungen werden nicht mehr korrekt oder nur noch langsam aufgebaut. Selbst neustarten des WebSocket-Servers hilft nicht. Irgendwann ist der Port einfach belegt, obwohl kein Programm auf ihm "lauscht".
Was mir dabei aufgefallen ist:

Nach ein paar tests, und mehrmaligem Prüfen von eventuell kritischen Stellen, hab ich mal versucht CloseNetworkConnection auszuklammern. Das ist die einzige Netzwerkfunktion, welche in einem anderen Thread ausgeführt wird. Und die soll nur dazu dienen bei manuellen oder durch den Client gewünschten verbindungsabbrüchen dies dem client mitzuteilen. Komischerweise läuft es jetzt seit über einer Stunde rund.

Dabei wird in der dokumentation nicht beschrieben, dass CloseNetworkConnection() nicht in einem anderen Thread ausgeführt werden darf. Und außer, dass es in einem anderen Thread aufgerufen wird, wüsste ich nicht was der Auslöser sein könnte. Dabei stelle ich sogar sicher, dass die client id, welche CloseNetworkConnection übergeben wird, gültig ist. Auch wird CloseNetworkConnection nicht aufgerufen, wenn ein client bereits durch #PB_NetworkEvent_Disconnect als getrennt signalisiert wurde.

Ich könnte noch testen ob das Problem noch besteht, wenn ich den client per CloseNetworkConnection im Hauptthread schließe, aber wenn es jetzt so funktioniert, dann belasse ich es erstmal.

Also die Lösung ist erstmal CloseNetworkConnection in der Lib auszukommentieren (Gibt nur eine Zeile). Wenn meine Tests hier noch weiter durchlaufen, werde ich das auch in der offiziellen Version ändern. Der Nachteil ohne CloseNetworkConnection ist nur, dass das manuelle trennen der Verbindung dem Client nicht signalisiert wird. Und natürlich wird die Verbindung nicht geschlossen, solange der client die nicht schließt.
Antworten