Pris en charge par
*Nécessite une version Indy personnalisée.
IOCP pour Windows est une API permettant de gérer des milliers de connexions à l'aide d'un pool de threads limité, au lieu d'utiliser un thread par connexion comme Indy le fait par défaut.
Pour activer IOCP pour les serveurs Indy, accédez à la propriété IOHandlerOptions et sélectionnez iohIOCP comme type IOHandler.
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 sont les threads utilisés pour les requêtes asynchrones IOCP (opérations avec chevauchement) ; par défaut, la valeur est zéro, ce qui signifie que le nombre de threads est calculé en fonction du nombre de processeurs (sauf pour Delphi 7 et 2007 où le nombre de threads est fixé à 32 car la fonction cpucount n'est pas prise en charge).
WorkOpThreads définit le nombre minimal de threads de travail maintenus prêts à traiter les requêtes, 0 par défaut. Un thread IOCP se contente de récupérer une opération terminée et confie le travail à ce pool, il n'est donc jamais bloqué par un client lent. Le pool grandit à la demande jusqu'à un maximum fixe dès que tous les threads de travail sont déjà occupés, il n'a donc pas besoin d'être dimensionné à l'avance. N'augmentez cette valeur que si vous souhaitez que le pool soit déjà prêt avant la première requête, ce qui évite de payer la création des threads pendant une rafale initiale de connexions.
Modifié dans la version 2026.9.0. WorkOpThreads liait auparavant chaque connexion à l'un de ces threads, de sorte que toutes les requêtes d'une connexion s'exécutaient sur le même thread, et WorkOpRoundRobin déterminait la façon dont les nouvelles connexions étaient réparties entre eux. Cette liaison a été supprimée : une connexion en attente du reste d'une requête bloquait toutes les autres connexions affectées au même thread, ce qui paralysait le serveur. Les requêtes d'une même connexion peuvent désormais s'exécuter sur des threads différents, il ne faut donc plus supposer que ce qui est conservé par thread, comme une connexion à une base de données ou un cache local au thread, suit une connexion. WorkOpRoundRobin n'existe plus. Retirez la propriété de votre code et, si vous l'aviez activée dans l'Object Inspector, supprimez également la ligne WorkOpRoundRobin du fichier .dfm de la fiche, sinon la fiche ne se charge pas.
PartialRequestTimeout permet au serveur d'attendre le reste d'un corps de requête HTTP dont il connaît déjà la longueur, en millisecondes et à 0 par défaut, ce qui le désactive. Sans cela, un corps de requête qui n'arrive pas en totalité au cours d'une seule complétion, par exemple un gros POST envoyé en plusieurs paquets, est abandonné silencieusement et la connexion est fermée sans réponse. L'attente ne s'exécute jamais sur un thread IOCP, qui dessert de nombreuses connexions et ne doit jamais être bloqué ; elle s'exécute sur le pool de threads de travail décrit ci-dessus, qui grandit à la demande jusqu'à un maximum fixe, de sorte qu'un client lent ou ne répondant pas ne peut pas l'épuiser ni retarder les autres connexions.
TCPKeepAlive permet au système d'exploitation de sonder les connexions inactives et de détecter un pair ayant disparu silencieusement (désactivé par défaut). Lorsque TCPKeepAlive.Enabled est défini sur True, le système d'exploitation commence à sonder une connexion après qu'elle est restée inactive pendant TCPKeepAlive.Time secondes (60 par défaut), en répétant l'opération toutes les TCPKeepAlive.Interval secondes (10 par défaut) jusqu'à ce que le pair réponde ou que la connexion soit abandonnée.
KeepAliveTimeout ferme toute connexion restée inactive plus longtemps que le nombre de secondes indiqué (0 par défaut, ce qui signifie désactivé). Seules les connexions inactives sont concernées ; une requête en cours de lecture ou une réponse en cours d'écriture n'est jamais interrompue par ce délai. C'est le comportement le plus proche de la façon dont l'IOHandler par défaut, à raison d'un thread par connexion, libère une connexion silencieuse, et il ne dépend ni du système d'exploitation ni d'une quelconque coopération du pair.
L'activation d'IOCP pour les serveurs Windows est recommandée lorsque vous devez gérer des milliers de connexions. Si votre serveur ne gère qu'un maximum de 100 connexions simultanées, vous pouvez conserver le modèle de thread Indy par défaut.
L'événement OnDisconnect ne se déclenche pas
IOCP fonctionne différemment du IOHandler Indy par défaut. Avec le IOHandler Indy par défaut, chaque connexion s'exécute dans un thread, et ces threads tournent en permanence en vérifiant si la connexion est active ; ainsi, en cas de déconnexion, celle-ci est notifiée dans un court délai.
IOCP fonctionne différemment ; il y a un pool de threads qui gère toutes les connexions, au lieu de 1 thread = 1 connexion comme Indy le fait par défaut. Pour IOCP, le seul moyen de détecter si une connexion est encore active est d'essayer d'écrire sur le socket. S'il y a une erreur, cela signifie que la connexion est fermée. Il y a 3 options pour détecter les déconnexions :
1. Si vous utilisez TsgcWebSocketClient, vous pouvez l'activer dans la propriété Options, CleanDisconnect := True (désactivé par défaut). Si cette option est activée, avant que le client se déconnecte, il envoie un message informant le serveur de la déconnexion, de sorte que le serveur recevra ce message et l'événement OnDisconnect sera déclenché.
2. Vous pouvez activer le heartbeat côté serveur, par exemple toutes les 60 secondes, il tentera d'envoyer un ping à tous les clients connectés et si un client est déconnecté, OnDisconnect sera appelé.
3. Vous pouvez activer TCPKeepAlive et/ou définir KeepAliveTimeout sur les IOHandlerOptions du serveur. Cela permet au serveur lui-même de détecter un pair devenu silencieux, par exemple parce que le client a planté ou que la connexion réseau s'est interrompue sans envoi de message de fermeture, et de fermer la connexion, sans dépendre du fait que le client envoie quoi que ce soit.