La façon de vérifier si vous pouvez écrire sur un socket est, de façon surprenante, d'essayer et écrire :-) il
Si la prise a été fermée, vous obtiendrez un code -1
de retour de write
et vous peut examiner errno
pour voir quel était le problème.
Si la prise est toujours valide, mais vous ne pouvez pas écrire des données au moment, write
renverra 0. L'appel read
se comporte aussi de la même façon, le retour -1
s'il y a un problème.
En gros, pour write
:
- si vous revenez un
-1
, il y a eu un problème et vous devriez vérifier errno
pour voir si elle est récupérable ou fatale.
- Si vous obtenez un
0
, vous ne pouvez rien écrire pour le moment (il peut s'agir d'un backlog réseau ou d'un autre problème mais certainement pas (encore) fatal).
- Si vous obtenez une valeur moins que ce que vous vouliez, alors certains ont été envoyés. Ajustez vos pointeurs afin que vous puissiez essayer d'envoyer le reste au prochain cycle. Ne pas supposer une valeur de retour positive signifie que le bloc entier a été envoyé.
- Si vous obtenez le même nombre d'octets que vous avez essayé d'envoyer, le tampon entier a été accepté pour livraison.
- Si vous obtenez plus que ce que vous avez demandé à envoyer, envoyez un email aux développeurs du noyau avec un commentaire acerbe. Linus et al adorera que :-)
Mise à jour: Comme l'a souligné la CAF dans les commentaires, j'ai oublié de prendre en compte le traitement du signal. Vous devez ignorer le signal de tuyau cassé ou write
échouera en interne en augmentant ce signal.
Vous pouvez le faire en insérant:
struct sigaction new_actn, old_actn;
new_actn.sa_handler = SIG_IGN;
sigemptyset (&new_actn.sa_mask);
new_actn.sa_flags = 0;
sigaction (SIGPIPE, &new_actn, &old_actn);
avant de commencer à utiliser les fonctions de socket. Vous pouvez ensuite utiliser:
sigaction (SIGPIPE, &old_actn, NULL);
pour restaurer la gestion du signal précédent.
Cela fonctionnera, et l'autre alternative est d'utiliser 'sigaction' pour ignorer' SIGPIPE' (mettre son gestionnaire à 'SIG_IGN'). – caf