Recommandations de conception d'application de socket
Avant d'utiliser une application de socket, évaluez les exigences fonctionnelles, les objectifs et les besoins de l'application de socket. Tenez également compte des exigences de performances et des impacts de l'application sur les ressources système.
La liste de recommandations suivante vous aide à résoudre certains de ces problèmes pour votre application de socket et vous indique de meilleures façons d'utiliser les sockets et de concevoir vos applications de socket:
| Recommandation | Motif | Meilleure utilisation dans |
|---|---|---|
| Utiliser les E-S asynchrones | Les E-S asynchrones utilisées dans un modèle de serveur à unités d'exécution sont préférables au modèle select () plus conventionnel. | Applications de serveur socket qui gèrent de nombreux clients simultanés. |
| Lors de l'utilisation d'E-S asynchrones, réglez le nombre d'unités d'exécution du processus sur un nombre optimal pour le nombre de clients à traiter. | Si trop peu d'unités d'exécution sont définies, certains clients peuvent arriver à un délai d'attente avant d'être traités. Si un trop grand nombre d'unités d'exécution est défini, certaines ressources système ne sont pas utilisées efficacement. Remarque: Il est préférable d'avoir trop d'unités d'exécution que trop peu d'unités d'exécution.
|
Applications de socket utilisant des E-S asynchrones. |
| Concevez une application de socket pour éviter l'utilisation du postflag sur toutes les opérations de démarrage pour les E-S asynchrones. | Permet d'éviter le temps système de la transition vers un port d'achèvement si l'opération a déjà été exécutée de manière synchrone. | Applications de socket utilisant des E-S asynchrones. |
| Utilisez send() et recv() sur read() et write(). | Les API send() et recv() offrent une petite amélioration des performances et de la serviçabilité par rapport à read() et write(). | Tout programme de socket qui le connaît utilise un descripteur de socket et non un descripteur de fichier. |
| Utilisez l'option de socket de réception basse eau (SO_RCVLOWAT) pour éviter de s'exécuter en boucle sur une opération de réception jusqu'à ce que toutes les données soient arrivées. | Permet à votre application d'attendre qu'une quantité minimale de données soit reçue sur le socket avant de satisfaire une opération de réception bloquée. | Toute application de socket qui reçoit des données |
| Utilisez l'indicateur MSG_WAITALL pour éviter la boucle sur une opération de réception jusqu'à ce que toutes les données soient arrivées. | Permet à votre application d'attendre que la totalité de la mémoire tampon fournie sur l'opération de réception soit reçue avant de satisfaire une opération de réception bloquée. | Toute application socket qui reçoit des données et qui sait à l'avance combien elle s'attend à arriver. |
| Utilisez sendmsg() et recvmsg() sur givedescriptor() et takedescriptor(). | Pour connaître les avantages, voir Descripteur passant entre les processus: sendmsg () et recvmsg () . | Toute application de socket transmettant des descripteurs de socket ou de fichier entre des processus. |
| Utilisez poll() sur select(). | Pour plus d'informations, voir Utilisation de poll () au lieu de select () . | Toute application de socket utilisant select() pour interroger le statut d'un socket. |
| Lorsque vous utilisez select(), essayez d'éviter un grand nombre de descripteurs dans l'ensemble de lectures, d'écritures ou d'exceptions. Remarque: Si vous utilisez un grand nombre de descripteurs pour le traitement select() , consultez la recommandation d'E-S asynchrone ci-dessus.
|
Lorsqu'il existe un grand nombre de descripteurs dans un ensemble de lectures, d'écritures ou d'exceptions, un travail redondant considérable se produit chaque fois que select() est appelé. Dès qu'un select() est satisfait, la fonction de socket réelle doit encore être exécutée, c'est-à-dire qu'une opération de lecture ou d'écriture ou d'acceptation doit encore être effectuée. Les API d'E-S asynchrones combinent la notification indiquant que quelque chose s'est produit sur un socket avec l'opération d'E-S réelle. | Applications ayant un grand nombre (> 50) de descripteurs actifs pour select(). |
| Sauvegardez votre copie des ensembles de lecture, d'écriture et d'exceptions avant d'utiliser select() afin d'éviter de régénérer les ensembles à chaque fois que vous devez réexécuter select(). | Cela permet d'économiser le temps système nécessaire à la régénération des ensembles de lecture, d'écriture ou d'exceptions à chaque fois que vous prévoyez d'émettre le select(). | Toute application de socket dans laquelle vous utilisez select() avec un grand nombre de descripteurs de socket activés pour la lecture, l'écriture ou le traitement des exceptions. |
| N'utilisez pas select() comme temporisateur. Utilisez sleep() à la place. Remarque: Si la granularité du temporisateur sleep() n'est pas adéquate, vous devrez peut-être utiliser select() comme temporisateur. Dans ce cas, définissez le nombre maximal de descripteurs sur 0 et la valeur de lecture, d'écriture et d'exception sur NULL.
|
Meilleure réponse du temporisateur et moins de surcharge du système. | Toute application de socket dans laquelle vous utilisez select() comme temporisateur. |
| Si votre application de socket a augmenté le nombre maximum de descripteurs de fichiers et de sockets autorisés par processus en utilisant DosSetRelMaxFH() et que vous utilisez select() dans cette même application, soyez attentif à l'impact de cette nouvelle valeur maximale sur la taille des ensembles de lecture, d'écriture et d'exception utilisés pour le traitement de select(). | Si vous allouez un descripteur en dehors de la plage de l'ensemble de lectures, d'écritures ou d'exceptions, comme indiqué par FD_SETSIZE, vous pouvez écraser et détruire la mémoire. Assurez-vous que les tailles de votre ensemble sont au moins suffisamment grandes pour gérer le nombre maximal de descripteurs défini pour le processus et la valeur maximale de descripteur spécifiée sur l'API select() . | Toute application ou processus dans lequel vous utilisez DosSetRelMaxFH() et select(). |
| Définissez tous les descripteurs de socket dans les ensembles de lecture ou d'écriture sur Non bloquant. Lorsqu'un descripteur est activé pour la lecture ou l'écriture, boucle et consomme ou envoie toutes les données jusqu'à ce que EWOULDBLOCK soit renvoyé. | Cela vous permet de réduire le nombre d'appels select() lorsque des données sont encore disponibles pour être traitées ou lues sur un descripteur. | Toute application de socket dans laquelle vous utilisez select(). |
| Indiquez uniquement les ensembles que vous devez utiliser pour le traitement select() . | La plupart des applications n'ont pas besoin de spécifier l'ensemble d'exceptions ou l'ensemble d'écritures. | Toute application de socket dans laquelle vous utilisez select(). |
Utilisez les API GSKit à la place de SSL_APIs. |
Global Security Kit (GSKit) et les API SSL_ vous permettent de développer des applications sécurisées de socket AF_INET ou AF_INET6, SOCK_STREAM. Etant donné que les API GSKit sont prises en charge sur les systèmes IBM , il s'agit des API préférées pour sécuriser une application. Les API SSL_ n'existent que dans le système d'exploitation IBM i. |
Toute application de socket devant être activée pour un traitement sécurisé. |
| Evitez d'utiliser des signaux. | La surcharge des performances des signaux (sur toutes les plateformes, et pas seulement sur la plateforme IBM i ) est coûteuse. Il est préférable de concevoir votre application de socket pour utiliser des API d'E-S asynchrones ou select() . | Toute application de socket qui utilise des signaux. |
| Utilisez des routines indépendantes du protocole, telles que inet_ntop(), inet_pton(), getaddrinfo()et getnameinfo(), lorsqu'elles sont disponibles. | Même si vous n'êtes pas encore prêt à prendre en charge IPv6, utilisez ces API (au lieu de inet_ntoa(), inet_addr(), gethostbyname() et gethostbyaddr()) pour vous préparer à une migration plus facile. | Toute application AF_INET ou AF_INET6 qui utilise des routines réseau. |
| Utilisez sockaddr_storage pour déclarer la mémoire pour n'importe quelle adresse de famille d'adresses. | Simplifie l'écriture de code portable sur plusieurs familles d'adresses et plateformes. Déclare suffisamment de mémoire pour contenir la plus grande famille d'adresses et garantit un alignement de limite correct. | Toute application de socket qui stocke des adresses. |