IOCP

Ondersteund door

 

TsgcWebSocketServer

TsgcWebSocketHTTPServer

 

*Vereist aangepaste Indy-versie.

 

IOCP voor Windows is een API die het afhandelen van duizenden verbindingen mogelijk maakt met behulp van een beperkte threadpool in plaats van één thread per verbinding zoals Indy standaard doet.

Om IOCP voor Indy-servers in te schakelen, gaat u naar de eigenschap IOHandlerOptions en selecteert u iohIOCP als IOHandler-type.


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 zijn de threads die worden gebruikt voor asynchrone IOCP-verzoeken (overlapping bewerkingen). Standaard is de waarde nul, wat betekent dat het aantal threads wordt berekend op basis van het aantal processors (met uitzondering van Delphi 7 en 2007, waar het aantal threads is ingesteld op 32 omdat de functie cpucount niet wordt ondersteund).

WorkOpThreads stelt het minimale aantal workerthreads in dat gereed wordt gehouden om verzoeken te verwerken, standaard 0. Een IOCP-thread pikt alleen een voltooide bewerking op en geeft het werk door aan deze pool, zodat hij nooit blokkeert op een trage client. De pool groeit op aanvraag tot een vast maximum zodra alle workerthreads al bezig zijn, zodat u de pool niet vooraf hoeft te dimensioneren. Verhoog deze waarde alleen als u wilt dat de pool al gereed is vóór het eerste verzoek, wat de kosten van het aanmaken van threads tijdens een eerste piek aan verbindingen voorkomt.

Gewijzigd in 2026.9.0. WorkOpThreads koppelde vroeger elke verbinding vast aan een van deze threads, zodat alle verzoeken van een verbinding op dezelfde thread werden uitgevoerd, en WorkOpRoundRobin bepaalde hoe nieuwe verbindingen daarover werden verdeeld. Die vaste koppeling is verwijderd: een verbinding die wachtte op de rest van een verzoek blokkeerde alle andere verbindingen die aan dezelfde thread waren toegewezen, waardoor de server tot stilstand kwam. Verzoeken van dezelfde verbinding kunnen nu op verschillende threads worden uitgevoerd, dus u mag er niet langer van uitgaan dat wat per thread wordt bewaard, zoals een databaseverbinding of een thread-lokale cache, een verbinding volgt. WorkOpRoundRobin bestaat niet meer. Verwijder de eigenschap uit uw code en verwijder, als u deze in de Object Inspector had ingeschakeld, ook de regel WorkOpRoundRobin uit het .dfm-bestand van het formulier, anders wordt het formulier niet geladen.

PartialRequestTimeout laat de server wachten op de rest van een HTTP-verzoekbody waarvan de lengte al bekend is, in milliseconden en standaard 0, wat betekent dat deze functie is uitgeschakeld. Zonder deze optie wordt een verzoekbody die niet volledig binnenkomt binnen één voltooiing, bijvoorbeeld een grote POST die in meerdere pakketten wordt verzonden, stilzwijgend verworpen en wordt de verbinding gesloten zonder antwoord. Het wachten wordt nooit uitgevoerd op een IOCP-thread, die veel verbindingen bedient en nooit mag blokkeren; het wordt uitgevoerd op de hierboven beschreven pool van workerthreads, die op aanvraag groeit tot een vast maximum, zodat een trage of niet-reagerende client deze pool niet kan uitputten en de andere verbindingen niet kan ophouden.

TCPKeepAlive laat het besturingssysteem inactieve verbindingen controleren en een peer detecteren die stilzwijgend is verdwenen (standaard uitgeschakeld). Wanneer TCPKeepAlive.Enabled is ingesteld op True, begint het besturingssysteem een verbinding te controleren nadat deze TCPKeepAlive.Time seconden (standaard 60) inactief is geweest, en herhaalt dit elke TCPKeepAlive.Interval seconden (standaard 10) totdat de peer antwoordt of de verbinding wordt verbroken.

KeepAliveTimeout sluit elke verbinding die langer inactief is geweest dan het opgegeven aantal seconden (standaard 0, wat betekent uitgeschakeld). Alleen inactieve verbindingen worden hierdoor beïnvloed; een verzoek dat wordt gelezen of een antwoord dat wordt geschreven, wordt nooit door deze timeout onderbroken. Dit komt het dichtst in de buurt van de manier waarop de standaard thread-per-verbinding IOHandler een stille verbinding vrijgeeft, en het is niet afhankelijk van het besturingssysteem of van enige medewerking van de peer.

 

Het inschakelen van IOCP voor Windows-servers wordt aanbevolen wanneer u duizenden verbindingen moet verwerken. Als uw server maximaal 100 gelijktijdige verbindingen afhandelt, kunt u het standaard Indy-threadmodel blijven gebruiken.

 

 

Gebeurtenis OnDisconnect wordt niet geactiveerd

 

IOCP werkt anders dan de standaard Indy IOHandler. Met de standaard Indy IOHandler wordt elke verbinding uitgevoerd in een thread en zijn deze threads de hele tijd actief om te controleren of de verbinding actief is; als er een verbreking optreedt, wordt dit binnen een korte periode gemeld.

 

IOCP werkt anders; er is een threadpool die alle verbindingen afhandelt in plaats van 1 thread = 1 verbinding zoals Indy standaard doet. Voor IOCP is de enige manier om te detecteren of een verbinding nog actief is, te proberen naar de socket te schrijven. Als er een fout is, betekent dit dat de verbinding is gesloten. Er zijn 3 opties om verbroken verbindingen te detecteren:

 

1. Als u TsgcWebSocketClient gebruikt, kunt u dit inschakelen in de eigenschap Options, CleanDisconnect := True (standaard uitgeschakeld). Als dit is ingeschakeld, verzendt de client een bericht aan de server voordat de verbinding wordt verbroken om de verbreking te melden, zodat de server dit bericht ontvangt en de gebeurtenis OnDisconnect wordt gegenereerd.

2. U kunt heartbeat inschakelen aan de serverzijde, bijvoorbeeld elke 60 seconden, zodat het een ping probeert te sturen naar alle verbonden clients. Als er een client verbroken is, wordt OnDisconnect aangeroepen.

3. U kunt TCPKeepAlive inschakelen en/of KeepAliveTimeout instellen op de IOHandlerOptions van de server. Hierdoor kan de server zelf een peer detecteren die stil is geworden, bijvoorbeeld omdat de client is gecrasht of de netwerkverbinding is verbroken zonder dat er een sluitbericht is verzonden, en de verbinding sluiten, zonder afhankelijk te zijn van iets dat de client verzendt.