web-dev-qa-db-fra.com

Comment utiliser l'option So_eekeealive correctement pour détecter que le client à l'autre extrémité est en panne?

j'essayais donc d'apprendre l'utilisation de l'option So_eekeekeealive dans la programmation de socket dans la langue C sous Environnement Linux.

J'ai créé une prise de serveur et utilisé mon navigateur pour vous connecter. C'était un succès et j'ai pu lire la demande d'obtention, mais je suis resté coincé sur l'utilisation de So_eekeekeealive.

J'ai vérifié ce lien [email protected] mais je n'ai pas trouvé d'exemple qui montre comment l'utiliser.

Dès que je détecte la demande du client sur accept() Fonction I définissez le SO_KEEPALIVE valeur d'option 1 Sur la prise du client. Maintenant, je ne sais pas comment vérifier si le client est en panne?, Comment changer l'intervalle de temps entre les sondes envoyées, etc.

Je veux dire comment vais-je obtenir le signal que le client est en panne (sans lecture ni écrire chez le client ... Je pensais que je voudrais obtenir un signal lorsque des sondes ne sont pas remplies de client), comment dois-je le programmer après avoir défini l'option So_ekeekeealive sur.

De plus, si supposons que les sondes soient envoyées toutes les 3 secondes et que le client tombe entre les deux, je ne connais pas que le client est en panne et que je puisse obtenir Sigpipe.

Quoi qu'il en soit, je veux savoir comment utiliser So_ekeekeealive dans le code.

Merci une tonne d'avance !!!

18
Durin

Pour modifier le nombre de sondes ou les intervalles de sonde, vous écrivez des valeurs au système de fichiers/proc.

 echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time
 echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl
 echo 20 > /proc/sys/net/ipv4/tcp_keepalive_probes

Notez que ces valeurs sont globales pour toutes les prises de conserve activées sur le système, vous pouvez également remplacer ces paramètres sur une base par socket lorsque vous définissez la section SetSockOpt, voir la section 4.2 du document que vous avez identifié.

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 de forcer la fin à distance pour accuser réception des paquets et de déterminer si la prise a mal tourné. Lorsque vous essayez d'écrire sur la prise, vous obtiendrez un sigpipe si Keepalive a déterminé que la partie distante est en panne.

20
bdk

Vous obtiendrez le même résultat si vous activez So_ekeekeealive, comme si vous n'agissez pas SO_KEKEALIVE - Généralement, vous trouverez la prise prête à l'emploi et obtenez une erreur lorsque vous l'avez lu.

Vous pouvez définir le délai de maintien de la base sur une base par souche sous Linux (cette fonction peut être une fonctionnalité spécifique à Linux). Je recommanderais cela plutôt que de changer le paramètre à l'échelle du système. Voir la page Homme pour TCP pour plus d'informations.

Enfin, si votre client est un navigateur Web, il est fort probable qu'il fermera le socket assez rapidement de toute façon - la plupart d'entre eux ne tiendront que des connexions Keepalive (HTTP 1.1) ouvertes pour un temps relativement court (30s, 1 min, etc.). Bien sûr, si la machine client a disparu ou le réseau vers le bas (qui est ce que So_ekeekeealive est vraiment utile pour la détection), il ne sera pas en mesure de fermer activement la prise.

10
MarkR

Comme déjà discuté, So_ekeekeealive rend le noyau plus agressif à la vérification continuellement de la vérification de la connexion même lorsque vous ne faites rien, mais ne remplace non change ou améliore la manière dont les informations vous sont livrées . Vous découvrirez lorsque vous essayez de faire quelque chose (par exemple "écrire"), et vous découvrirez tout de suite que le noyau ne fait que signaler le statut d'un drapeau précédemment défini, plutôt que d'attendre quelques-uns secondes (ou beaucoup plus longtemps dans certains cas) pour l'échec de l'activité réseau. La même logique de code que vous avez eu pour la manipulation de "l'autre côté est parti de manière inattendue" sera toujours utilisée; Quels changements sont le calendrier (pas la méthode).

Pratiquement chaque programme de prises "pratiques" fournit en quelque sorte non - bloquant l'accès aux sockets pendant la phase de données (peut-être avec sélectionner ()/sondage (), ou peut-être avec FCNTL ( )/O_nonblock/einprogress & ewouldblock, ou si votre noyau le supporte peut-être avec msg_dontwait). En supposant que cela soit déjà fait pour d'autres raisons, il est trivial (n'exigeant parfois aucun code) d'en outre, découvrez immédiatement une connexion de connexion. Mais si la phase de données n'est-elle pas déjà en quelque sorte fournit un accès non bloquant aux sockets, vous ne le découvrirez pas de la connexion avant la prochaine fois que vous essayez de faire quelque chose.

(A TCP Connexion de socket sans une sorte de comportement non bloquant pendant 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 de "suspendre". indéfiniment, et il n'y a pas beaucoup de choses que vous pouvez faire à ce sujet.)

3
Chuck Kollars

Réponse courte, ajouter

int flags =1;
if (setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags))) { perror("ERROR: setsocketopt(), SO_KEEPALIVE"); exit(0); };

sur le côté serveur, et read() sera débloqué lorsque le client est en panne.

Une explication complète peut être trouvée ici .

3
Alt Eisen