TCP Listener Sehr viele Daten empfangen
-
Hallo,
ich würde gerne ein Programm schreiben welches über TCP Daten empfangen soll diese dann in eine Datenbank abspeichern soll. Der Aufbau ist folgendermaßen aufgebaut.
Server mit TCP Listener (empfängt die Daten)
Client welches einen String sendet (ca. 2000 Clients)Jetzt sollen die Daten empfangen und abgespeichert werden. Das system muss schnell und Stabil laufen. Wie sollte ich das Programm am besten Programieren. Vorgenommen hatte ich es in c++ zu programieren unter Windows. Was muss ich verwenden was brauchen ich ? Threads? Sockets?
Ein paar Tipps würden mir gut tun. Vielen Dank schonmal.
-
Threads? Sockets?
Klingt passend. Hast du denn schon Erfahrung? Das ist nämlich nicht trivial.
-
In C++ habe ich erfahrung. Jedoch noch nicht mit Sockets oder Threads?
Welches ist den Richtig. Es soll nämlich auch zum Beispiel mehrere Clients gleichzeitig handeln können.
-
Hallo,
beides ist richtig,
aber es ist schwer, ohne genaue Anforderung, was dazu zu sagen.Ich würde versuchen die Anzahl Threads einzuschränken:
z.B.
Der Main Thread behandelt alle Clients und pushed die Daten in eine Queue (FIFO).
Ein Datenkbank Thread transportiert die Daten von der Queue in die Datenbank.Gruß Frank
-
Vielen Dank für die Antworten,
aber ich habe gelesen das wenn ich Threads benutze es Probleme geben kann.
z.b.
Wenn Client1 einen String sendet wird ein neuer Thread eröffnet. Dann sendet aber gleichzeitig auch Client2 und Client3 zum gleichen Zeitpunkt einen Thread. So werden 3 Threads eröffnet und der Client1 wird doch zuletzt abgearbeitet oder ?
-
Hallo Memoo,
Wenn du für jeden Client einen Thread verwendest,
dann ist die Abarbeitungsreihenfolge bei bis zu 2000 threads willkürlich
und nicht vorhersehbar.
Es ist korrekt was du gelesen hast.Das genau würde ich nicht machen:
Über TCP wird die Datenrate geringer sein,
als die maximale Schreibgeschwindigkeit mit der man die Daten einen FIFO (RAM) schreiben kann.
Deswegen alleine braucht man also an dieser Stelle nicht mit Threads zu arbeiten.Das Schreiben in die Datenbank ist da schon aufwändiger
und könnte ohne Threads die Clients unnötig ausbremsen.Gruß Frank
-
Hallo Frank,
danke für deine Antwort. Also soll ich für das empfangen keine Threads aber für das eintragen in die DB Threads verwenden
???Soll ich also z.B. für jede Client anfrage einen Socket eröffnen die Daten in einen BUF schreiben einen Thread eröffnen welche dann die Daten in die DB einspeichert?
Oder hast du eine bessere Idee welche mir auf die Sprünge hilft.
-
Keiner eine Idee?
-
Da die Schreiboperationen in die Datenbank vermutlich alle blockierend sind, reicht dafür ein Thread. Also ein Thread für die Kommunikation und einer für die Datenbankzugriffe.
-
Welches ist den Richtig. Es soll nämlich auch zum Beispiel mehrere Clients gleichzeitig handeln können.
Viele Wege fuehren nach Rom, manche via Threads, andere ueber Prozesse und wieder andere ueber select.
Also soll ich für das empfangen keine Threads aber für das eintragen in die DB Threads verwenden?? Soll ich also ...
Es gibt kein soll, nur ein guenstig oder unguenstig. Klar kannst du 2000 Threads benutzen, aber ob es unguenstig, kann pauschal nicht gesagt werden.
aber ich habe gelesen das wenn ich Threads benutze es Probleme geben kann.
Was meinst du? Mit einem Brotmesser kann es auch Probleme geben.
-
Könntest auch Erlang nehmen
Da erübrigt sich das ganze Thread-Zeugs komplett.
-
Ich würde das lieber nicht mit Windows machen. Linux und dev/epoll sind am besten skalierbar, selbst select hätte unter Linux maximal 1024 mögliche Verbindungen, Windows nur 64. Wenn es richtig performant werden soll (für Windows): Thread-Pools und IO-Completion Ports. Ob das im Gegensatz zu Linux performant ist? Eher nicht. Wie wäre es mit Apache + Python/PHP? Dann wärst du die Socket-Probleme etwas los, denn wenn du dich damit noch nicht auskennst, ist es unwahrscheinlich, dass dein Resultat auf Anhieb super ist, deshalb empfehle ich, vorhandene Server zu nutzen.
-
@Ad aCTa
ist kein wirkliches Argument, man kann ja select mehrfach aufrufen. Außerdem hängt die Maximalanzahl Sockets pro select afaik nur von FD_SIZE ab, das kann man ja auf einen beliebigen Wert setzen.
Sinnvollerweise hat man ein oder zwei Threads, die alle Daten einsammeln und einen weiteren, der das Zeug in der Datenbank verstaut.
-
> das kann man ja auf einen beliebigen Wert setzen.
Nein, die fd_sets sind AFAIK intern Bitfelder, die du nicht willkürlich verändern kannst.
> ist kein wirkliches Argument, man kann ja select mehrfach aufrufen.
Wenn sie nicht blockieren, ja. Non-blocking-selects sind aber nun wirklich nicht die Bombe was Leistung angeht.
-
FD_SIZE ist ein Makro, das dann wohl die Feldgröße bestimmt.
Und naja, select ist doch genau dazu da, um bei blocking sockets herauszufinden, welche von ihnen gerade "bereit" zum Empfangen/Senden sind.
-
> FD_SIZE ist ein Makro, das dann wohl die Feldgröße bestimmt.
Exakt, aber AFAIK ist das read-only gedacht, wegen Bitfeldern. Mit Linux könnte man es tatsächlich ändern, danach muss aber der ganze Kernel neu kompiliert werden, was bei Windows schwierig werden könnte. Du könntest mehrere fd_sets nutzen und mit mehreren selects() und mit timeouts evtl. was werkeln, aber 32 selects mit timeouts finde ich nicht skalierbar, dann warten sie letzten fd's alle timeouts ab, bis sie drankommen. Threads verschlimmbessern das m.E. dann auch nur noch.
-
Entweder 64 Verbindungen pro Thread oder eben weniger Threads und einen sofortigen Timeout und evtl. ein (sehr) kurzes Sleep ganz am Ende um die CPU etwas zu schonen.
Bei 2000 Verbindungen muss man sich noch nicht so den Kopf über Performance zerbrechen (angenommen dass pro Client höchstens ein paar kurze Strings pro Sekunde kommen). Wahrscheinlich wird eher die Datenbank der Flaschenhals werden.Ach ja, um mal http://support.microsoft.com/?scid=kb%3Ben-us%3B111855&x=6&y=12 zu zitieren:
The maximum number of sockets that a Windows Sockets application can use is determined at compile time by the manifest constant FD_SETSIZE. To do this, [...]
Wie ernst man das nehmen kann, weiß ich nicht, da die Aussage sowieso schon Unfug ist. Die Maximalzahl Sockets in einem Programm hat rein gar nichts mit FD_SETSIZE zu tun.
-
hi
es waere mal interessant zu wissen, ob die 2000 clients alle mit dem server verbunden bleiben oder ob er 2000 clients hat die sich nur dann verbinden, wenn sie paar zeichen rueber senden wollen.
ein kleiner ueberblick was performance angeht:
http://technixlab.de/net_performance.jpgob die datenbank ein flaschenhals ist oder nicht kann man bis dato nicht beurteilen.
meep meep
-
Hallo Leute,
also 2000 Clients senden alle 30 sec. einen String.
So läuft es ungefähr ab:Client meldet sich Verbindung herstellen
Sendet String Daten empfangen
Client geht (weis aber nicht ob er selber die Verbindung trennt)Die müssen nicht dauerhaft verbunden sein nur dan wen ein string empfangen werden soll. Kann aber auch vorkommen das sich mehrer Clients gleichzeitig melden.
-
in diesem fall wuerde ich einen server mit hausnummer 50 threads machen. die 50 nehmen verbindungen an, empfangen den string, werfen den in eine queue und beenden die verbindung. wenn mal mehr als 50 clients zur gleichen zeit connecten wollen, dann kommt der rest in eine warteschlange. sollte aber ruck zuck gehen.
kannst dann ja mit der anzahl der threads rumspielen bis du einen halbwegs optimalen wert gefunden hast. es gibt aber keine veranlassung 2000 threads dafuer aufzubauen
ein einzelner thread schiebt dann die daten aus der queue in die datenbank
meep meep