Unterstützt von
*Erfordert die benutzerdefinierte Indy-Version.
IOCP für Windows ist eine API, die die Verarbeitung Tausender Verbindungen mit einem begrenzten Thread-Pool ermöglicht, anstatt wie Indy standardmäßig einen Thread pro Verbindung zu verwenden.
Um IOCP für Indy-Server zu aktivieren, gehen Sie zur Eigenschaft IOHandlerOptions und wählen Sie iohIOCP als IOHandler-Typ.
Server.IOHandlerOptions.IOHandlerType := iohIOCP;
Server.IOHandlerOptions.IOCP.IOCPThreads := 0;
Server.IOHandlerOptions.IOCP.WorkOpThreads := 0;
Server.IOHandlerOptions.IOCP.PartialRequestTimeout := 0;
Server.IOHandlerOptions.IOCP.TCPKeepAlive.Enabled := True;
Server.IOHandlerOptions.KeepAliveTimeout := 120;
IOCPThreads sind die Threads, die für IOCP-asynchrone Anfragen (überlappte Operationen) verwendet werden; standardmäßig ist der Wert null, was bedeutet, dass die Anzahl der Threads anhand der Anzahl der Prozessoren berechnet wird (außer bei Delphi 7 und 2007, wo die Anzahl der Threads auf 32 gesetzt wird, da die Funktion cpucount nicht unterstützt wird).
WorkOpThreads legt die Mindestanzahl an Worker-Threads fest, die zur Verarbeitung von Anfragen bereitgehalten werden, standardmäßig 0. Ein IOCP-Thread nimmt nur eine abgeschlossene Operation entgegen und übergibt die Arbeit an diesen Pool, sodass er niemals durch einen langsamen Client blockiert wird. Der Pool wächst bei Bedarf bis zu einem festen Maximum, sobald alle Worker bereits beschäftigt sind, er muss also nicht im Voraus dimensioniert werden. Erhöhen Sie diesen Wert nur, wenn der Pool schon vor der ersten Anfrage bereitstehen soll, was die Kosten für das Erzeugen von Threads während eines anfänglichen Ansturms von Verbindungen vermeidet.
Geändert in 2026.9.0. WorkOpThreads band früher jede Verbindung fest an einen dieser Threads, sodass alle Anfragen einer Verbindung im selben Thread liefen, und WorkOpRoundRobin bestimmte, wie neue Verbindungen auf diese Threads verteilt wurden. Diese feste Bindung wurde entfernt: Eine Verbindung, die auf den Rest einer Anfrage wartete, blockierte alle anderen Verbindungen, die demselben Thread zugewiesen waren, und legte den Server lahm. Anfragen derselben Verbindung können jetzt in unterschiedlichen Threads laufen. Bei allem, was pro Thread gehalten wird, etwa einer Datenbankverbindung oder einem Thread-lokalen Cache, darf daher nicht mehr davon ausgegangen werden, dass es einer Verbindung folgt. WorkOpRoundRobin existiert nicht mehr. Entfernen Sie die Eigenschaft aus Ihrem Code, und wenn Sie sie im Object Inspector aktiviert hatten, löschen Sie auch die Zeile WorkOpRoundRobin aus der .dfm-Datei des Formulars, sonst wird das Formular nicht geladen.
PartialRequestTimeout lässt den Server auf den Rest eines HTTP-Anfragetexts warten, dessen Länge bereits bekannt ist, in Millisekunden und standardmäßig 0, was die Funktion deaktiviert. Ohne diese Option wird ein Anfragetext, der nicht vollständig innerhalb einer einzigen Completion eintrifft, zum Beispiel ein großer POST, der in mehreren Paketen gesendet wird, stillschweigend verworfen und die Verbindung ohne Antwort geschlossen. Die Wartezeit läuft niemals in einem IOCP-Thread ab, der viele Verbindungen bedient und niemals blockieren darf, sondern in dem oben beschriebenen Worker-Pool, der bei Bedarf bis zu einem festen Maximum wächst, sodass ein langsamer oder nicht reagierender Client ihn nicht erschöpfen und die übrigen Verbindungen aufhalten kann.
TCPKeepAlive ermöglicht es dem Betriebssystem, inaktive Verbindungen zu prüfen und einen Peer zu erkennen, der stillschweigend verschwunden ist (standardmäßig deaktiviert). Wenn TCPKeepAlive.Enabled auf True gesetzt ist, beginnt das Betriebssystem eine Verbindung zu prüfen, nachdem sie TCPKeepAlive.Time Sekunden lang inaktiv war (standardmäßig 60), und wiederholt dies alle TCPKeepAlive.Interval Sekunden (standardmäßig 10), bis der Peer antwortet oder die Verbindung abgebrochen wird.
KeepAliveTimeout schließt jede Verbindung, die länger als die angegebene Anzahl von Sekunden im Leerlauf war (standardmäßig 0, was deaktiviert bedeutet). Betroffen sind nur Verbindungen im Leerlauf, eine Anfrage, die gerade gelesen wird, oder eine Antwort, die gerade geschrieben wird, wird von diesem Timeout niemals unterbrochen. Das kommt dem am nächsten, wie der standardmäßige IOHandler mit einem Thread pro Verbindung eine stumme Verbindung freigibt, und es hängt weder vom Betriebssystem noch von einer Mitwirkung des Peers ab.
Das Aktivieren von IOCP für Windows-Server wird empfohlen, wenn Sie Tausende von Verbindungen handhaben müssen. Wenn Ihr Server nur maximal 100 gleichzeitige Verbindungen handhabt, können Sie beim Standard-Indy-Thread-Modell bleiben.
OnDisconnect-Ereignis nicht ausgelöst
IOCP funktioniert anders als der Standard-Indy-IOHandler. Mit dem Standard-Indy-IOHandler läuft jede Verbindung in einem Thread, und diese Threads laufen die ganze Zeit und prüfen, ob die Verbindung aktiv ist, sodass bei einer Trennung diese in kurzer Zeit gemeldet wird.
IOCP funktioniert anders, es gibt einen Thread-Pool, der alle Verbindungen bedient, anstelle von 1 Thread = 1 Verbindung, wie es Indy standardmäßig tut. Bei IOCP besteht die einzige Möglichkeit festzustellen, ob eine Verbindung noch aktiv ist, darin, zu versuchen, in den Socket zu schreiben. Tritt dabei ein Fehler auf, bedeutet das, dass die Verbindung geschlossen ist. Es gibt 3 Optionen, um Trennungen zu erkennen:
1. Wenn Sie TsgcWebSocketClient verwenden, können Sie es in der Eigenschaft Options aktivieren, CleanDisconnect := True (standardmäßig deaktiviert). Wenn es aktiviert ist, sendet der Client vor dem Trennen eine Nachricht, die den Server über die Verbindungstrennung informiert, sodass der Server diese Nachricht empfängt und das Ereignis OnDisconnect ausgelöst wird.
2. Sie können heartbeat auf der Server-Seite aktivieren, zum Beispiel alle 60 Sekunden, sodass versucht wird, einen Ping an alle verbundenen Clients zu senden, und wenn ein Client getrennt ist, wird OnDisconnect aufgerufen.
3. Sie können TCPKeepAlive aktivieren und/oder KeepAliveTimeout in den IOHandlerOptions des Servers setzen. Damit kann der Server selbst einen Peer erkennen, der verstummt ist, zum Beispiel weil der Client abgestürzt ist oder die Netzwerkverbindung abgebrochen wurde, ohne eine Close-Nachricht zu senden, und die Verbindung schließen, ohne darauf angewiesen zu sein, dass der Client etwas sendet.