Building Multi-threaded TCP/IP-Server
Will ich bauen eine TCP/IP-server, der verwendet wird um bis zu 100 gleichzeitigen clients, aber immer noch nicht sicher, wie, um loszulegen.
zumindest ich brauche den server um diese:
- Hören-client, und speichern Sie Sie auf array oder eine Liste.
- für jeden client, müssen Sie empfangen und senden von Daten basierend auf der client-status.
- Sollte der server aktualisiert die clients-Liste, wenn jemand eine Verbindung herstellen oder trennen.
- Lieber zur Arbeit als Dienst mit GUI zu verwalten.
Könnte mir jemand helfen wie man anfangen,die ich sah indy Probe, aber Sie nicht helfen, sah auch für die meisten Komponenten aber noch auf der Suche.
- So referenziert in anderen Fragen, wenn Sie Ihre wirkliche Anzahl der clients größer als 1000 ist, könnten Sie haben einige große Speicherauslastung, wenn Indy ist eingerichtet mit einem thread pro concurrent client. Mit async oder Fortsetzung basierten Ansätzen, ist es möglich, das Sie bewältigen konnten viele weitere verbindungen mit weniger threads. stackoverflow.com/questions/37185/...
- Sie möchten möglicherweise überprüfen Sie heraus-ICS-Komponenten von Francois Piette und vergleichen. Einige Leute finden, die Indy besser für Sie, einige Leute finden, die ICS besser für Sie.
- Ich denke, dass der blockierende Ansatz ist falsch gemacht in den meisten Fällen. Hab nach einem thread aktiv für die gesamte Lebensdauer der die Sitzung / das Objekt ist schlicht und einfach falsch. Sie brauchen nur einen taks / thread-pool und für jede einzelne Anfrage, die Sie verwenden ein thread aus dem pool. Auf diese Weise haben Sie nur so viele threads, da gibt es viele gleichzeitige Anfrage läuft bei der gleichen Zeit. Und viel Glück erreichte sogar 100 gibt.
- Indy bietet 3 Arten von Scheduler: Thread-basierte, Thread mit thread-pool und Glasfaser-basierte. Standardmäßig Indy benutzt die einfache thread-basierten scheduler. Wenn Sie einen thread-pool, alles, was Sie tun müssen, ist, weisen Sie ein TIdSchedulerOfThreadPool Beispiel Ihren IdTCPServer.Scheduler-Eigenschaft.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie die
TidTCPServer
die Multithread-innen. Keine Notwendigkeit für Sie zu verwalten, die Fäden. Alles ist transparent, so in der Art, wie Sie schreiben, die Anwendung für einen Mandanten, in (fast) auf die gleiche Weise, die Sie schreiben wird es für viele. Finden Sie dieOnConnect
Veranstaltung. Es ist einTidContext
parameter, die eine TThreadList innen. Sie können verwenden Sie das Ereignis, auf 'registrieren',/fügen Sie Ihre Kunden zu Ihren benutzerdefinierten array/Liste undOnDisconnect
zum entfernen des clients.Den
OnExecute
Ereignis wird ausgelöst, wenn der server eine Nachricht empfängt. Verwenden Sie Ihre Parameter zu Lesen, die Nachricht, die gesendet wird.Außerdem müssen Sie anderen Anwendung, die Ihre client, mit
TidTCPClient
. In dieser Anwendung können Sie die Adresse des Servers (finden Sie in der Host-Eigenschaft) sowie der Hafen, die übereinstimmen sollten mit dem server ein. Rufen SieConnect
(wenn der server läuft) und zum senden von Zeichenfolgen, die Sie habenSendCmd
Methode. (Siehe auchIOHandler.WriteLn
wenn Sie wollen)Es gibt auch andere Dinge, aber ich denke, das ist genug, um Ihnen den Einstieg. Auch Sie können post in Embarcadero Foren im .Delphi.Winsock-forum, wo der Indy-team-Mitglieder sind schwebend über. Oder vielleicht können Sie Fragen direkt in .Delphi.Nicht-Technische und die Jungs dort werden Sie zu führen.
Ein weiterer Ansatz ist DataSnap das ist eine mehr objektorientierte Schicht über Indy (nicht zu verwechseln mit DBX), die gibt Ihre JSON, REST und andere leckereien. Finden Sie für einen kleinen Rückblick auf hier.
Execute
Veranstaltung hat als parameter denAContext: TidContext
. So haben SieAContext.Connection
wo Sie haben genug Methoden zum senden von Daten an den client zB.AContext.Connection.SendCmd
. Auch haben Sie dieAContext.Connection.Socket
Eigenschaft (IIRC), welcher einem seiner (sub -) Eigenschaften die IP-Adresse des client, der die Nachricht gesendet hat. Sie können dies als ein 'clientID', wenn Sie wollen, zu tun, Protokollierung etc.Und anderen Delphi-library option wäre synapse, die ein einfaches framework, das beliebig erweitert werden. Es ist ein IOCPPool demo verfügbar, in die dazu beigetragen Dateien, die weiterhelfen können.
Synapse ist mehr ein framework von Klassen als eine Komponenten-Bibliothek. Es ist eine lebendige und aktive Benutzer-community, die bereit ist, Unterstützung jeder Herausforderung. Ich benutze diese Bibliothek in Delphi 2010 ohne irgendwelche Probleme (obwohl ich die neueste Entwickler-version aus dem SVN).
Werden, da Sie nicht die Bauteile, es ist sehr einfach zu verwenden der Klassen in einfachen Konsolenanwendungen oder windows-Dienste.
Auf einer Windows-Plattform sind Sie wahrscheinlich am besten zu vermeiden
select
für eine große Anzahl von gleichzeitigen verbindungen (100 ist nicht eine große Anzahl von verbindungen, obwohl). Allerdings avirtuos ist richtig, dass Sie vermeiden möchten "thread pro Verbindung" - Modelle. Die meisten effizienter Ansatz unter Windows ist die Verwendung von overlapped I/O und I/O Completion Ports. Sie ermöglicht die Verwaltung von 10s von tausenden von verbindungen mit einer kleinen Anzahl von Fäden (2 oder 3 vielleicht).Habe ich keine Delphi-Erfahrung, so habe ich keine Ahnung, wie einfach es ist, zu interagieren, die mit C++ - code, ABER ich habe einen freien C++ - I/O Completion-Port-server-framework (ab hier) das würde zumindest zeigen, wie Sie die standard-Win32-Abschluss-I/O-Port-API arbeitet. Es könnte für Sie nützlich sein und Sie könnten in der Lage sein, etwas zu tun, ähnlich wie in Delphi.
Indy ist Ihre beste Wahl : 1000 clients sind nicht viel : ich habe entwickeln einem server, die dienen mussten, 4-5 k-clients und es funktioniert wie ein Charme.
--> für die Klienten, die Liste, du könntest in einer Schleife durch die TThreadList Mitglied des TidTCPServer (version 9.0), die speichert alle "lebendig" - threads, jeder thread ist "äquivalent" zu einer client-Verbindung, obwohl die Fäden konnten, überleben ein client die Verbindung, aber das könnte man beheben, indem man eine entsprechende Verbindung timeout-Wert. Wenn Sie möchten, könnten Sie auch pflegen Sie Ihre eigenen Kunden-Liste (Erben von TList zum Beispiel, oder erstellen Sie ein Generika.Sammlung): fügen Sie die client-info ' s nach der Sie die Software onConnect-Ereignis (tidPeerThread-Klasse stellt alle client-infos: IP,...)
Würden Sie dann eine Schleife durch diese Liste in regelmäßigen Abständen und überprüfen alive-verbindungen (ping-Kommando) und kill/löschen Sie alle zombies.
[indy-Dokumentation]
Event-handler für peer-Gewinde-Verbindung versucht.
Eigentum die Software onConnect: TIdServerThreadEvent;
Beschreibung
Software onConnect ist ein event handler für TIdServerThreadEvents. Die Software onConnect tritt auf, wenn ein TIdPeerThread versucht, eine Verbindung zu einem TIdTCPServer.
Software onConnect erhält als parameter AThread, die die TIdPeerThread thread, der die Verbindung anfordert.
Weisen eine TIdServerThreadEvent event-handler-Prozedur, um die Software onConnect.
[/indy-Dokumentation]
für jeden client, müssen Sie empfangen und senden von Daten basierend auf der client-status :
--> überprüfen Sie die chat-client-und server-demo-Quellcode für ein detailliertes Beispiel.
Lieber zur Arbeit als Dienst mit GUI zu managen : Sie entwickeln könnte eine service-Anwendung, die würden sich alle von Ihrer Tätigkeit in eine DB und eine zweite app, die würde, die db und weisen alle verfügbaren Statistiken (Kunden-Nummer...).
und hier sind die links zu Indy 9.0 (Quellen und Dokumentation) :
http://www.indyproject.org/downloads/Indy_9_00_14_src.zip
http://www.indyproject.org/downloads/Indy-9-0-Help-WinHelp.zip
Und hier ist ein Indy-Buch obwohl ich nicht glaube, Sie würde es brauchen, nach dem Lesen der Dokumentation: Indy in depth : http://www.atozed.com/Indy/Book/index.EN.aspx
Hier ein gutes tutorial :
http://www.devarticles.com/c/a/Delphi-Kylix/Creating-Chat-Application-with-Borland-DelphiIndy-The-Client/
Glück
100 sockets nicht dass viele. Sie konnte sich überhaupt die Mühe, mit so etwas wie epoll(), aber für diesen Fall würde ich nur einen einzelnen FD_SET mit alle sockets, select() auf den gesamten Satz, prüfen Sie dann, und Verfahren Sie in der Reihenfolge. Wenn ich etwas tun musste, das war möglicherweise zeitaufwendige, würde ich die Verwendung eines thread-pool für den message-Handler.
Einige hervorragende Komponenten-sets, die sind nützlich für Situationen wie deine (und vieles mehr) sind kbmMW und Die. Es gibt einige andere gute sets, auch, denke ich, könnten Sie tun, eine Suche nach Archiv oder stellen Sie eine Frage in Embarcaderos' Delphi thirdpartytools newsgroup. Sie können die search-Archive hier:
http://codenewsfast.com/
Ich habe mir vor kurzem dieses problem. Hier ist ein link zu einem C++ Beispiel mit EPOLL zu verwalten Hunderte von multicast-sockets. Dir wäre TCP/IP, aber das ist wirklich nur ein einfaches ändern.
Welche überhaupt Methode Sie wählen, für 100+ gleichzeitige sockets/clients, die Sie verwenden möchten, ein thread-Modell, das sich auf Umfrage, wählen Sie, oder vorzuziehen, epoll, wenn Ihre Plattform unterstützt wird.
http://anthonyvirtuoso.com/public/dokuwiki/doku.php/projects:multiplexreceiverepoll
@jfawcett - wählen Sie auf mehr als ~50 FDs kommt mit einem ziemlich großen CPU-hit, je nachdem, wie oft Sie tatsächlich ausführen, die Sie wählen. In meinem Kommentar oben, dass die Beispiel-Klasse wurde ursprünglich mit select, aber nachdem ich die CPU-Kosten (valgrind w/callgrind) wechselte ich zu epoll. Aber sicherlich wählen Sie eine gültige option.