Comment utiliser SO_KEEPALIVE option correctement détecter que le client à l'autre extrémité est en panne?
donc j'essayais d'apprendre l'utilisation de l'option SO_KEEPALIVE dans le support de la programmation en langage C sous environnement Linux.
J'ai créé un serveur de socket et utilisé mon navigateur pour se connecter à elle. Il a été un succès et j'ai été capable de lire la requête GET, mais je suis coincé sur l'utilisation de SO_KEEPALIVE.
J'ai vérifié ce lien [email protected] mais je ne pouvais pas trouver un exemple qui montre comment l'utiliser.
Dès que je détecte la demande du client sur accept()
fonction que j'ai mis le SO_KEEPALIVE
valeur de l'option 1
sur le socket client.
Maintenant, je ne sais pas comment faire pour vérifier si le client est en panne?, Comment faire pour modifier l'intervalle de temps entre les sondes envoyées etc.
Je veux dire, comment vais-je recevoir le signal que le client est en bas (sans lecture ou de l'écriture chez le client...j'ai pensé que je vais obtenir un signal lorsque les sondes sont pas répondu de nouveau à partir d'un client), comment dois-je programmer après le réglage de l'option SO_KEEPALIVE sur.
Aussi si supposons que les sondes sont envoyées toutes les 3 secondes et le client va vers le bas entre les deux, je ne vais pas à savoir que le client est en panne et que je puisse obtenir SIGPIPE.
De toute façon important, je veux savoir comment utiliser SO_KEEPALIVE dans le code.
Merci une tonne à l'avance!!!
Vous devez vous connecter pour publier un commentaire.
De modifier le nombre de sondes ou de la sonde intervalles, vous écrivez des valeurs pour le système de fichiers /proc comme
Noter que ces valeurs sont globaux pour tous les keepalive permis de sockets sur le système, Vous pouvez également modifier ces paramètres par socket base lorsque vous définissez la setsockopt, voir la section 4.2 du document lié.
Vous ne pouvez pas "vérifier" l'état de la prise de l'espace utilisateur avec keepalive. Au lieu de cela, le noyau est tout simplement plus agressif pour forcer l'extrémité distante de reconnaître les paquets, et de déterminer si la prise est endommagée. Lorsque vous essayez d'écrire sur le support, vous obtiendrez un signal SIGPIPE si keepalive a déterminé extrémité distante est en baisse.
printf("%d\n",read(clientsockfd,buff,BUFSIZ)); sleep(5); x = read(clientsockfd,buff,BUFSIZ); printf("%d--%s\n",x,strerror(errno)); sleep(3); x = read(clientsockfd,buff,BUFSIZ); printf("%d--%s\n",x,strerror(errno));
Dans le premier cas, j'ai mis le garder vivant et le second cas, de ne pas fixer de garder en vie sur. dès que j'ai envoyer la demande de navigateur, je ferme l'onglet. La sortie est la même pour les deux cas408 0--Success 0--Success
je.e pas d'erreur sur la lecture à partir d'un dead peer, même après le réglage de la garder vivante sur. Plutôt donne 0 octets lus.Vous obtiendrez le même résultat si vous activez SO_KEEPALIVE, comme si vous n'activez pas SO_KEEPALIVE - typiquement, vous allez trouver la douille de prêt et obtenez une erreur lorsque vous lisez à partir d'elle.
Vous pouvez définir le keepalive délai d'attente par socket base sous Linux (ce qui peut être spécifique à Linux, fonctionnalité). Je recommande ce plutôt que de changer le système de l'échelle de réglage. Voir la page de man pour le protocole tcp pour plus d'info.
Enfin, si votre client est un navigateur web, il est fort probable qu'elle va fermer le socket assez rapidement de toute façon la plupart d'entre eux ne détiennent keepalive (HTTP 1.1) les connexions ouvertes sur un laps de temps relativement court (30 s, 1 min, etc). Bien sûr, si la machine cliente a disparu réseau ou vers le bas (qui est ce que SO_KEEPALIVE est très utile pour détecter), alors il ne sera pas en mesure de activement fermer le socket.
Réponse courte, ajouter
sur le côté serveur, et
read()
sera débloqué lorsque le client est en baisse.Une explication complète peut être trouvée ici.
Comme déjà discuté, SO_KEEPALIVE rend le noyau le plus agressif en permanence vérifier la connexion, même lorsque vous ne faites rien, mais ne pas modifier ou d'améliorer la façon dont l'information est fournie pour vous. Vous trouverez lorsque vous essayez de faire réellement quelque chose (par exemple, "écrire"), et vous verrez tout de suite puisque le noyau est maintenant juste des rapports sur l'état d'un indicateur défini, plutôt que de devoir attendre quelques secondes (voire beaucoup plus dans certains cas) pour l'activité du réseau à l'échec. Exactement la même logique de code vous avez eu pour la manipulation de "l'autre côté s'en alla de façon inattendue" condition sera toujours utilisé; ce qui change est le moment (pas la méthode).
Pratiquement tous les "pratiques" prises de programme, d'une certaine façon fournit non-blocage de l'accès aux prises au cours de la phase de données (peut-être avec select()/poll(), ou peut-être avec fcntl()/O_NONBLOCK/EINPROGRESS&EWOULDBLOCK, ou si votre noyau prend en charge avec peut-être MSG_DONTWAIT). En supposant que cela est déjà fait pour d'autres raisons, il est trivial (parfois nécessitant pas de code du tout) en plus de trouver tout de suite sur une connexion de laisser tomber. Mais si la phase de données ne pas déjà d'une certaine manière non-blocage de l'accès aux sockets, vous ne trouverez pas sur la connexion à l'abandon jusqu'à la prochaine fois que vous essayez de faire quelque chose.
(Un socket TCP connexion sans une sorte de non-blocage de comportement au cours de la phase de données est notoirement fragile, comme si le mauvais paquet rencontre un problème de réseau, il est très facile pour le programme, ensuite, de "s'accrocher" pour une durée indéfinie, et il n'y a pas beaucoup que vous pouvez faire à ce sujet.)