12
votes

Vérifiez la connexion ouverte ou fermée? (En C sous Linux)

Dans la programmation de socket dans Linux, je dois écrire des données dans la prise, mais je ne sais pas que la prise est ouverte ou proche. Comment savoir que je sais que cette prise est ouverte et ferme sans lire? XXX

J'ai lu depuis SOCKFD et je suis sûr que cette connexion est ouverte. Quand écrire un tampon dans Newsockfd, je ne sais pas Newockfd est ouvert ou fermer comment vérifier Newockfd est fermé?


Je connais le problème. au milieu de la connexion d'écriture fermée. Par exemple, écrire 1024 données en 500 Connexion fermée et programmée fermée. Comment éviter cela?


0 commentaires

3 Réponses :


20
votes

Le moyen de vérifier si vous pouvez écrire sur une prise, c'est étonnamment, d'essayer de vous écrire: -)

Si la prise a été fermée, vous obtiendrez un -1 code> code de retour de écrire code> et vous pouvez examiner errno code> pour voir quel était le problème. p>

Si la prise est toujours valide mais que vous ne pouvez pas écrire Toute données pour le moment, écriture code> retournera 0. L'appel code> Lecture code> se comporte également de la même manière, renvoyant -1 code> s'il y a un problème. p>

Fondamentalement, pour écrire code>: p>

  • Si vous récupérez un -1 code>, il y a eu un problème et vous devriez vérifier errno code> pour voir si elle est recouvrable ou fatale. Li>
  • Si vous récupérez un 0 code>, vous ne pouvez rien écrire pour le moment (peut être un arriéré réseau ou un autre problème, mais certainement, pas (encore) fatal). LI>
  • Si vous obtenez une valeur de moins que ce que vous vouliez, alors certains em> des données ont été envoyés. Ajustez vos pointeurs afin que vous puissiez essayer d'envoyer le reste au prochain cycle. Les pas em> supposent qu'une valeur de retour positive signifie que l'ensemble du bloc a été envoyé. Li>
  • Si vous récupérez le même numéro que le nombre d'octets que vous avez essayé d'envoyer, tout le tampon a été accepté pour la livraison. LI>
  • Si vous revenez plus que ce que vous avez demandé d'être envoyé, envoyez un courrier électronique aux développeurs du noyau avec un commentaire acerbic. Linus et al aimeront que: -) li> ul>

    Mise à jour: EM> Comme la CAF a souligné dans les commentaires, j'ai oublié de prendre en compte la manipulation du signal. Vous devez ignorer le signal de tuyau cassé ou écrire code> échouera en interne en augmentant ce signal. P>

    Vous pouvez le faire en insertant: p>

    sigaction (SIGPIPE, &old_actn, NULL);
    


5 commentaires

Dans la ligne suivante, voir si (n <= 0) mais en fonction de la fonction d'écriture, une erreur s'est produite et fermée


@Sjb, do pas suppose des problèmes si écrire retourne 0. Cela peut se produire s'il y a un arriéré de réseau temporaire. Si l'arriéré tourne dans un vrai problème, la session sera arrêtée et vous finirez par obtenir -1. Jusque-là, continuez à essayer.


Je connais le problème. au milieu de la connexion d'écriture fermée. Par exemple, écrire 1024 données en 500 Connexion fermée et programmée fermée


PAX, vous oubliez que, par défaut, essayez de écrire sur la prise fermé par l'autre extrémité entraînera la rétention de votre processus de rétention d'un signal Sigpipe , dont l'action par défaut de laquelle est de mettre fin au processus.


Mon erreur. Corrigé maintenant (espérons-le).



8
votes

La programmation de la prise peut être plutôt délicate, car vous ne savez souvent pas qu'une erreur s'est produite tant que plus tard.

Par exemple, si la machine que vous écrivez pour s'éteindre anormalement, l'appel d'écriture peut réussir (car vous avez pu écrire sur vos tampons d'exploitation internes), seulement pour échouer pendant l'appel proche.

Sauf si vous avez une méthode de vérification de la couche d'application de vérification du socket (c'est-à-dire envoyer un message et nécessitant une réponse dans une période de temps), vous n'avez aucun moyen de savoir. Si vous utilisez un protocole standard, quelque chose peut déjà exister pour gérer les erreurs.

La réponse courte est donc que vous devez vérifier les retours d'erreur de chaque appel qui touche la prise (lecture, écriture, fermeture, etc.).


1 commentaires

Malheureusement, c'est la bonne réponse. J'ai essayé quelques façons de savoir si les connexions HTTP conservées sont toujours valables, mais ce n'est pas fiable et sans conditions de course.



16
votes

J'utilise Envoyer () Écrivez () qui ne traite aucun signal: xxx


1 commentaires

Cela fonctionnera et l'autre alternative est d'utiliser sigaction pour ignorer sigpipe (définir son gestionnaire sur sig_ign ).