détecter lorsqu’une application côté client ferme la connexion

Je développe un serveur 9p, il ressemble beaucoup à un serveur nfs. Le assembly et le déassembly ultérieurs ne provoquent aucune fuite du fichier descripteur de socket car je suis capable de fermer le socket. Toutefois, dans le scénario suivant, le serveur ne nettoie pas correctement et ne ferme pas le socket. Le scénario est le suivant: lorsque le client de la machine A monte un FS à partir de la machine serveur. Ensuite, pour une raison quelconque, la machine A redémarre ou est arrêtée. Si cela se produit, je m’attends à ce que le serveur nettoie le travail et ferme le socket, mais pour une raison quelconque, il bloque read (). Je pensais qu’un read () devrait renvoyer 0 lorsqu’une connexion est fermée mais ce n’est pas le cas. Je suppose que c’est parce qu’une terminaison TCP correcte ne s’est pas produite, de sorte que le serveur attend des données du client. Voici un pseudo code de mon serveur

while(1){ n = read(sockfd, buffer, 4); //4 is protocol header that specifies the size if ( n == 0 ) break; /* iteratively read the rest of bytes until the incoming message ends */ } cleanup(); // close socket and some other tasks 

Cependant, lorsque le client redémarre alors que le serveur se bloque en lecture, rien ne se produit. Quel est le meilleur moyen et le plus facile à résoudre? Certaines personnes suggèrent d’exécuter un thread séparé qui vérifie les connexions, mais cela est trop impliqué. Je suis sûr qu’il doit y avoir un moyen plus rapide

Lorsque le client effectue un arrêt, le système d’exploitation du client met fin à toute connexion TCP. Mais lorsque le client tombe en panne ou est éteint ou lorsqu’un problème de réseau survient quelque part entre le client et le serveur, il est impossible de fournir des informations au serveur et le serveur peut être bloqué dans l’appel read() pour toujours.

Il y a deux solutions possibles. Soit vous pouvez utiliser les sondes TCP keep alive standard ou vous pouvez implémenter une vérification de santé au niveau de l’application.

TCP rest en vie

TCP keep-alive est bien décrit par exemple à http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html :

Pour comprendre ce que fait TCP keepalive (que nous appellerons justement keepalive), il suffit de lire le nom: garder TCP en vie. Cela signifie que vous pourrez vérifier votre socket connecté (également connu sous le nom de sockets TCP) et déterminer si la connexion est toujours active ou si elle est cassée …

Lorsque vous souhaitez que votre application utilise le protocole TCP, restz actif. Il suffit de définir l’option socket (la vérification des erreurs est manquante):

 int optval = 1; socklen_t optlen = sizeof(optval); setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen); 

TCP keep alive est facile à utiliser, mais cela dépend de la configuration du système d’exploitation et de l’application ne peut pas définir ses propres délais d’attente car ils sont configurables à l’échelle du système.

Vérification de l’état de l’application

Utilisez un mécanisme au niveau de l’application lorsque vous avez besoin de délais d’attente spécifiques à l’application pour la détection de la déconnexion. Il existe de nombreuses façons de le mettre en œuvre. L’idée est d’envoyer périodiquement des données inutiles et de supposer que la connexion est détruite lorsqu’elle n’est pas reçue.

Je veux modifier la bonne réponse de Zaboj Campula avec le moyen le plus important de régler ce problème: les délais d’attente. Normalement, vous atsortingbuez un délai d’attente à toute opération de socket. Une valeur typique est 30 secondes. De cette façon, il n’est pas nécessaire de restr en vie la plupart du temps. La panne de connexion sera détectée dans les 30 secondes.

Certaines personnes suggèrent d’exécuter un thread séparé qui vérifie les connexions, mais cela est trop impliqué.

Cela ne fonctionne pas car votre machine ne sait pas que la connexion a disparu. Il n’y a rien à vérifier.