Arrêt gracieux, options Linger et fermeture du socket

Les informations suivantes sont fournies pour clarifier le sujet de l’arrêt des connexions de socket fermant les sockets. Il est important de faire la différence entre l’arrêt d’une connexion de socket et la fermeture d’un socket.

L’arrêt d’une connexion de socket implique un échange de messages de protocole entre les deux points de terminaison, ci-après appelé séquence d’arrêt. Deux classes générales de séquences d’arrêt sont définies : gracieux et avorté (également appelé dur). Dans une séquence d’arrêt normale, toutes les données qui ont été mises en file d’attente, mais pas encore transmises peuvent être envoyées avant la fermeture de la connexion. Lors d’un arrêt avorté, toutes les données non enentrées sont perdues. L’occurrence d’une séquence d’arrêt (gracieuse ou abandonnée) peut également être utilisée pour fournir une indication FD_CLOSE aux applications associées indiquant qu’un arrêt est en cours.

La fermeture d’un socket, en revanche, entraîne la désaffectation du handle de socket afin que l’application ne puisse plus référencer ou utiliser le socket de quelque manière que ce soit.

Dans les sockets Windows, la fonction d’arrêt et la fonction WSASendDisconnect peuvent être utilisées pour lancer une séquence d’arrêt, tandis que la fonction closesocket est utilisée pour libérer les handles de socket et libérer toutes les ressources associées. Une certaine confusion découle toutefois du fait que la fonction closesocket provoque implicitement une séquence d’arrêt si ce n’est pas déjà arrivé. En fait, il est devenu une pratique de programmation plutôt courante de s’appuyer sur cette fonctionnalité et d’utiliser closesocket pour lancer la séquence d’arrêt et libérer le handle de socket.

Pour faciliter cette utilisation, l’interface sockets fournit des contrôles au moyen du mécanisme d’option de socket qui permet au programmeur d’indiquer si la séquence d’arrêt implicite doit être normale ou avortée, et si la fonction closesocket doit s’attarder (qui n’est pas terminée immédiatement) pour laisser le temps à une séquence d’arrêt avec grâce. Ces importantes distinctions et les ramifications de l’utilisation de closesocket de cette manière ne sont pas encore largement comprises.

En établissant les valeurs appropriées pour les options de socket SO_LINGER et SO_DONTLINGER, vous pouvez obtenir les types de comportement suivants avec la fonction closesocket :

  • Séquence d’arrêt abandonnée, retour immédiat de closesocket.
  • Arrêt correct, retardant le retour jusqu’à ce que la séquence d’arrêt se termine ou qu’un intervalle de temps spécifié s’écoule. Si l’intervalle de temps expire avant la fin de la séquence d’arrêt avec grâce, une séquence d’arrêt avortée se produit et la fermeture retourne .
  • Arrêt gracieux, retour immédiat, ce qui permet à la séquence d’arrêt de se terminer en arrière-plan. Bien qu’il s’agisse du comportement par défaut, l’application n’a aucun moyen de savoir quand (ou si) la séquence d’arrêt avec grâce se termine réellement.

L’utilisation des options de socket SO_LINGER et SO_DONTLINGER, ainsi que la structure persistante associée, est abordée plus en détail dans les sections de référence sur les options de socket SOL_SOCKET et la structure linger .

Une technique qui peut être utilisée pour réduire le risque de problèmes lors de la suppression de la connexion consiste à éviter de s’appuyer sur un arrêt implicite initié par closesocket. Utilisez plutôt l’une des deux fonctions d’arrêt explicites, shutdown ou WSASendDisconnect. Cela entraîne la réception d’une indication FD_CLOSE par l’application homologue indiquant que toutes les données en attente ont été reçues. Pour illustrer cela, le tableau suivant montre les fonctions qui seraient appelées par les composants client et serveur d’une application, où le client est chargé d’initier un arrêt normal.

Côté client Côté serveur
(1) Appelle la ou les arrêt(s, SD_SEND) pour signaler la fin de session et que le client n’a plus de données à envoyer.
(2) Reçoit FD_CLOSE, indiquant un arrêt normal en cours et que toutes les données ont été reçues.
(3) Envoie toutes les données de réponse restantes.
(importance du moment local uniquement) Obtient FD_READ et appelle recv pour obtenir toutes les données de réponse envoyées par le serveur . (4) Appelle le ou les arrêt(s, SD_SEND) pour indiquer que le serveur n’a plus de données à envoyer.
(5) Reçoit FD_CLOSE indication. (importance du moment local uniquement) Appelle closesocket .
(6) Appelle closesocket.