Client-Server wie geht man vor?

Für allgemeine Fragen zur Programmierung mit PureBasic.
fabulouspaul
Beiträge: 120
Registriert: 01.04.2011 21:59

Client-Server wie geht man vor?

Beitrag von fabulouspaul »

Hallo Gemeinde,

ich will einen Server programmieren, der auf Anfragen von mehreren Clients reagiert und mit ihnen Daten austauscht.
Da ich noch nicht genau sagen kann wie viele Clients es werden, möchte ich es möglichst flexibel gestalten.

Meine Idee dazu ist, das ganze mit Threads zu realisieren:
  • 1 Thread für den Empfang von Datenpaketen (diese sollen in eine Empfangs-Queue geschoben werden)
  • 1 Thread für den Versand von Daten (aus einer Sende-Queue)
  • 1 (oder mehrere) Thread(s) zum bearbeiten der Empfangs-Queue bzw. zum befüllen der Sende-Queue
Dazu das Hauptprogramm, dass eine kleine GUI über den aktuellen Server-Status anzeigt und das Starten und Stoppen des Servers ermöglicht.

Bevor ich damit losrenne meine Fragen an das "Schwarmwissen": Macht das so Sinn? Seht Ihr Stolpersteine, auf die ich achten sollte? Habt Ihr sonst noch Anregungen dazu?
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Client-Server wie geht man vor?

Beitrag von NicTheQuick »

In den meisten Fällen macht es Sinn einen Hauptthread zu haben, der auf neue Verbindungen von Clienten wartet und dann für jede neue Verbindung mit einem Clienten einen eigenen Thread startet, der dann für das Empfangen und das Senden von Daten auf dieser Verbindung verantwortlich ist.

Bei deinem Vorschlag mit den Threads für's Senden und Empfangen könnte es ein Problem geben, sobald ein Client unerwartet die Verbindung verliert oder sie plötzlich sehr langsam ist. Das könnte den kompletten Verkehr für alle anderen Pakete in der Sende- oder Empfangs-Queue aufhalten, obwohl die nächsten Pakete womöglich für einen ganz anderen Clienten gedacht sind und dieser keine Verbindungsprobleme hat.

Hier oder im englischen Forum gibt es ein komplett fertiges Modul für die Arbeit mit dem Netzwerk und Threads. Ich weiß aber nicht mehr genau welches das war. Auf Anhieb finde ich nur das hier: https://www.purebasic.fr/english/viewtopic.php?p=543746 (deutsche Beschreibung ist im Modul selbst)
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Client-Server wie geht man vor?

Beitrag von STARGÅTE »

NicTheQuick hat geschrieben: 20.03.2023 13:54 Bei deinem Vorschlag mit den Threads für's Senden und Empfangen könnte es ein Problem geben, sobald ein Client unerwartet die Verbindung verliert oder sie plötzlich sehr langsam ist. Das könnte den kompletten Verkehr für alle anderen Pakete in der Sende- oder Empfangs-Queue aufhalten, obwohl die nächsten Pakete womöglich für einen ganz anderen Clienten gedacht sind und dieser keine Verbindungsprobleme hat.
Vielleicht übersehe ich hier was, aber ein "langsamer" Client sollte doch überhaut keine Einschränkung für Sende- und Empfangs-Loop (Thread) sein.
Bei SendNetworkData() wird doch praktisch "sofort" dieser Befehl ausgeführt und die Programmausführung nicht angehalten, das eigentliche Senden findet doch im Hintergrund statt.
Das gleiche gilt bei ReceiveNetworkData(). Hier gibt es doch nur dann ein Server-Event wenn die Daten schon da sind und mit ReceiveNetworkData nur "verschoben" werden müssen.

Ich hätte jetzt gesagt, dass ein Sende- und Empfangs-Thread reicht.
In meinen Projekten habe ich es im Prinzip so gehandhabt wie fabulouspaul vorschlägt.
Stolperstein wäre hier nur die Queue selber, nämlich wenn eine Queue nicht mehr schnellgenug abgearbeitet werden kann, also z.B. der Server-Netzwerkpuffer vollläuft oder zwar alles ruckzuck empfangen wird, aber die Bearbeitung der Daten länger dauert.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Client-Server wie geht man vor?

Beitrag von NicTheQuick »

Hm, womöglich hast du Recht. Ich kenne es von anderen Projekten so wie ich es geschrieben habe. Aber bei Purebasic ist es ja definitiv so, dass dazwischen noch Puffer sind. Die Frage ist dann höchstens noch für mich: Kann es passieren, dass man einem Clienten Daten schicken will und das aber nicht funktioniert, weil der Sendepuffer schon voll ist und der SendNetworkData()-Befehl hängen bleibt? Oder funktioniert das dann immer einwandfrei?
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 6996
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Client-Server wie geht man vor?

Beitrag von STARGÅTE »

Stimmt. Entgegen der Dokumentation bleibt SendNetworkData() tatsächlich hängen und gibt nicht -1 zurück.
Das ist natürlich blöd und ist mir glaube ich schon mal aufgefallen jetzt wo du es sagst, finde aber den Thread nicht mehr.

Code: Alles auswählen

CreateNetworkServer(1, 7000)
Con = OpenNetworkConnection("localhost", 7000)

*Buffer = AllocateMemory(65536)
Repeat
	Debug SendNetworkData(Con, *Buffer, 65536)
	Delay(100)
ForEver
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Client-Server wie geht man vor?

Beitrag von NicTheQuick »

Puh, dann hatte ich ja doch nicht ganz unrecht. Dann müsste man jetzt noch testen, ob andere Threads weiterhin SentNetworkData() nutzen könnten, wenn ein einzelner Thread daran hängen bleibt. Dafür braucht man dann natürlich zwei verschiedene Connections. Entweder zum selben Server und der Server nimmt nur die Daten des einen Clienten entgegen, oder zu zwei verschiedenen Servern.
Bin aber gerade ehrlich gesagt zu faul einen Testcode dafür zu schreiben. ^^
Bild
Antworten