Serverprogrammierung - Theorie?
-
Epic

-
cooky451 schrieb:
Du kannst mehrere Verbindungen mit select() "überwachen". Trotzdem würde ich Multithreading vorziehen.
Warum?
cooky451 schrieb:
(Sowohl was Performance, als auch was den Aufwand angeht.)
Der Aufwand ist doch viel höher mit der ganzen Synchronisation. Und schneller wird das dadurch auch nicht automatisch.
cooky451 schrieb:
Viel "Interthreadkommunikation" hast du da ja nicht, insofern ist das kein Problem.
Mehr davon als unbedingt nötig ist immer schlecht. Und hier hätte man sehr wohl nicht-triviale Synchronisation. Mal ganz abgesehen davon, dass man
acceptundrecvnicht abbrechen kann, also kann so ein Programm schwer korrekt terminieren.cooky451 schrieb:
Mit einem modernen Compiler kannst du sogar C++11 std::thread, std::future etc. nutzen, die sind wirklich leicht zu verwenden.
NOT
Wenn etwas dabei rauskommen soll, nimm die asynchronen Sockets von Boost.Asio. Und lass bloß die Finger von Threads.
-
TyRoXx schrieb:
NOT
Ja...

-
TyRoXx schrieb:
Wenn etwas dabei rauskommen soll, nimm die asynchronen Sockets von Boost.Asio. Und lass bloß die Finger von Threads.

Wobei ich jetzt nicht unbedingt gegen Threads bin. Aber sicherlich nicht 1 Thread pro Client, das ist Overkill.
-
Immer wieder schön die ganzen fundierten Antworten hier.
Wo sind eigentlich die Evangelisten abgeblieben? Ich beginne die schon fast zu vermissen...
-
Threads sind reichlich low-level. Da nimmt man dann doch besser etwas höher angesiedelte Funktionalitäten. Leider hats nicht allzu vieles in den Standard geschafft, was darüber liegt. Bestenfalls wäre da noch std::async/std::future zu nennen. Ich denke mal, dass boost.asio ein guter Kompromiss ist, um noch PLattformunabhängig zu bleiben.
-
Also dein Rechner ist sozusagen ein Server. Du kannst ihn auch als Server verwenden nur der verbraucht dann mehr strom als herkömmliche Server. Es gibt auf Windows und Linux Bibliotheken die du verwenden kannst um Informationen zwischen Client und Server zu tauschen. z.B wenn du ein Chat programmierst ist das Chat Fenster der Client und wenn du z.B auf deinem Rechner ein Server aufbaust und dich mit dem Chat Fenster in dem Server verbindest und ein anderer Rechner sich auch mit dem Client in dem Server verbindet kannst du über den Server nachrichten versenden. Du programmierst den Client so das er eine Nachrichten versenden kann der Server muss dann eine Nachricht empfangen können und versendet die Nachricht dann an alle anderen Rechner die auch mit dem Server verbunden sind.
Wenn ich ein Fehler drin hab bitte verbessern.
Gruss
-
TyRoXx schrieb:
Mal ganz abgesehen davon, dass man
acceptundrecvnicht abbrechen kann, also kann so ein Programm schwer korrekt terminieren.Erstens könnte man die entsprechenden Sockets in non-blocking Modus versetzen. Aber das ist nicht mal erforderlich, denn zweitens kehren sowohl accept als auch recv zurück, wenn man die entsprechenden Sockets schließt.
-
Belli schrieb:
TyRoXx schrieb:
Mal ganz abgesehen davon, dass man
acceptundrecvnicht abbrechen kann, also kann so ein Programm schwer korrekt terminieren.Erstens könnte man die entsprechenden Sockets in non-blocking Modus versetzen. Aber das ist nicht mal erforderlich, denn zweitens kehren sowohl accept als auch recv zurück, wenn man die entsprechenden Sockets schließt.
Was accept oder recv macht, wenn man den Socket schließt, ist meines Wissens nicht spezifiziert. Besser ist es, tatsächlich mit non-blocking zu arbeiten und erst dann accept bzw. recv aufzurufen, wenn auch tatsächlich jemand anklopft.
Die Entscheidung zwischen asynchron oder multithreaded kann man nicht so einfach beantworten, dass das eine einfacher und das andere schneller ist.
Also von der Komplexität geben die 2 Modelle sich nicht viel. Beides ist nicht ganz trivial. Einen Server zu implementieren ist halt eben nicht trivial.
Performancemässig hängt es von der Applikation ab. Wenn ein einzelner Request relativ viel Verarbeitung verursacht, ist es besser, den Request in einen separaten Thread zu verarbeiten, damit andere Verbindungen nicht blockiert werden. Bei wenig Verarbeitung ist in der Regel der asynchrone Ansatz schneller, da kein Kontextwechsel statt findet und keine Synchronisierung notwendig ist.
-
tntnet schrieb:
Was accept oder recv macht, wenn man den Socket schließt, ist meines Wissens nicht spezifiziert. Besser ist es, tatsächlich mit non-blocking zu arbeiten und erst dann accept bzw. recv aufzurufen, wenn auch tatsächlich jemand anklopft.
Da kann man auch gleich
selectnehmen. Oder funktioniert das ganz anders?
-
tntnet schrieb:
Besser ist es, tatsächlich mit non-blocking zu arbeiten und erst dann accept bzw. recv aufzurufen, wenn auch tatsächlich jemand anklopft.
Lieber select fragen.
tntnet schrieb:
Performancemässig hängt es von der Applikation ab.
Nö. Asynchrone Modelle dürften immer schneller sein. Nur merkt man das eben erst ab einer ordentlichen Menge Clienten.
tntnet schrieb:
Also von der Komplexität geben die 2 Modelle sich nicht viel. Beides ist nicht ganz trivial. Einen Server zu implementieren ist halt eben nicht trivial.
Doch, ein Pong Server ist extrem trivial. Und genau das ist das Problem. Wo will man bei einem trivialen Problem vernünftige Argumente für Lösungen finden.
-
Asynchrone Verarbeitung und Threads sind keine orthogonalen Konzepte. Man kann auch beides haben.
-
TyRoXx schrieb:
tntnet schrieb:
Was accept oder recv macht, wenn man den Socket schließt, ist meines Wissens nicht spezifiziert. Besser ist es, tatsächlich mit non-blocking zu arbeiten und erst dann accept bzw. recv aufzurufen, wenn auch tatsächlich jemand anklopft.
Da kann man auch gleich
selectnehmen. Oder funktioniert das ganz anders?Das ist doch genau das, worauf ich hinaus wollte. Hätte ich vielleicht direkt darauf hinweisen sollen. Also Socket auf non-blocking und dann mit
selectwarten, bis jemand anklopft. Und imselectkann man dann noch eine pipe rein packen, womit ich den select geordnet wecken kann, wenn ich den Server runter fahren möchte.cooky451 schrieb:
tntnet schrieb:
Performancemässig hängt es von der Applikation ab.
Nö. Asynchrone Modelle dürften immer schneller sein. Nur merkt man das eben erst ab einer ordentlichen Menge Clienten.
Das stimmt so nicht. Wenn die Verarbeitung einer Antwort signifikant lange dauert, dann ist das besser, wenn er in einem separaten Thread verarbeitet wird. Ein rein asynchroner Thread läuft auf genau einem Core und wenn ein Request bearbeitet wird, müssen die anderen warten.
Nehmen wir ein einfaches Rechenmodell: Ein Request kommt an und der Server braucht eine Sekunde, um die Antwort zu generieren. Während er die Antwort generiert, kann er im asynchronen Modell keine weiteren Requests verarbeiten. Er schafft also genau einen Request pro Sekunde. Wird der Request in einem Thread generiert, kann ein anderer Thread bereits den nächsten Request entgegennehmen und verarbeiten. Habe ich dann beispielsweise 8 Cores, kann der multithreaded Server halt 8 Requests pro Sekunde verarbeiten.
-
Man kann immer noch (meine Posts liest ja offenbar niemand) asynchrone IO mit beliebig vielen Threads verwenden. Dein Beispiel ist daher totaler Schwachsinn.
-
tntnet schrieb:
Also Socket auf non-blocking und dann mit
selectwarten, bis jemand anklopft.Genau, erst non-blocking machen, und dann zur Sicherheit noch mal select fragen, das ist ein Plan.

@threads Das hat dann aber nichts mehr mit I/O Performance zu tun.
-
Ich kapere den thread kurz mal für eine kleine Frage:
Ich würde gerne einen minichat clienten basteln. Da ich die select variante doof finde, wrde ich gerne threads verwenden.
Würde zwei threads, je einen für recv und send(main aktualisiert nur das chatfenster), verwenden.
Kann ich den erstellten socket an die threads übergeben ohne das Fehler passieren? Laut dem was ich gelesen habe funktioniert direkte Übergabe per Referenz nicht, da sich durch die threads(gebe nur wieder was ich gelesen habe), die Speicheradresse(der socketvariable) ändert(oder ändern kann).
-
Adressen von Variablen ändern sich grundsätzlich niemals, allerdings kann die Variable im anderen Thread zerstört werden, während du noch eine Referenz auf sie hast.
Übergib einfach by value und gut ist.
-
314159265358979 schrieb:
Asynchrone Verarbeitung und Threads sind keine orthogonalen Konzepte. Man kann auch beides haben.
Weil orthogonale Konzepte bildlich auf zwei Dimension liegen, x- und y-Achse, kannst man sie unabhänig von einander steuern. Deine Nutzung macht mir allerdings Kopfschmerzen.

-
Athar schrieb:
Adressen von Variablen ändern sich grundsätzlich niemals, allerdings kann die Variable im anderen Thread zerstört werden, während du noch eine Referenz auf sie hast.
Übergib einfach by value und gut ist.Geht leider bei C Posix nicht(ich weiß hier ist es c++, dachte läuft ähnlich. Zumal ich dachte, dass das dann nicht funktioniert).
Hier das Beispiel das ich meinte:
" This example performs argument passing incorrectly. It passes the address of variable t, which is shared memory space and visible to all threads. As the loop iterates, the value of this memory location changes, possibly before the created threads can access it. "
https://computing.llnl.gov/tutorials/pthreads/#PassingArguments
Beispiel 3.Wieso solte sich der Wert des Speicherorts ändern oO
-
Namenloser324 schrieb:
Athar schrieb:
Adressen von Variablen ändern sich grundsätzlich niemals, allerdings kann die Variable im anderen Thread zerstört werden, während du noch eine Referenz auf sie hast.
Übergib einfach by value und gut ist.Geht leider bei C Posix nicht(ich weiß hier ist es c++, dachte läuft ähnlich. Zumal ich dachte, dass das dann nicht funktioniert).
Hier das Beispiel das ich meinte:
" This example performs argument passing incorrectly. It passes the address of variable t, which is shared memory space and visible to all threads. As the loop iterates, the value of this memory location changes, possibly before the created threads can access it. "
https://computing.llnl.gov/tutorials/pthreads/#PassingArguments
Beispiel 3.Wieso solte sich der Wert des Speicherorts ändern oO
ACH, lol, die meinen der Wert der an dieser Adresse steht, oder?