Address already in use avec boost asio accepteur
J'ai écrit un serveur qui est à l'écoute pour incomming les connexions TCP et les clients à se connecter à elle. Quand j'ai arrêté le serveur et de le redémarrer sur le même port, j'ai parfois le message d'erreur EADDRINUSE lors de l'appel de bind(...) (code d'erreur: 98 sur Linux). Cela se produit même si je suis à la définition de l'option de réutiliser le support.
L'erreur ne se produit pas tout le temps, mais il semble qu'il se produit le plus souvent lorsque les clients sont connectés au serveur et l'envoi de données alors qu'il s'arrête. Je crois que le problème c'est qu'il y a encore des connexions en attente pendant que le serveur est arrêté (rubrique connexe: https://stackoverflow.com/questions/41602/how-to-forcibly-close-a-socket-in-time-wait).
Sur le côté serveur, j'utilise boost::asio::ip::tcp::accepteur. Je l'initialiser avec l'option "reuse_address" (voir http://beta.boost.org/doc/libs/1_38_0/doc/html/boost_asio/reference/basic_socket_acceptor.html). Voici l'extrait de code:
using boost::asio::ip::tcp;
acceptor acceptor::acceptor(io_service);
endpoint ep(ip::tcp::v4(), port);
acceptor.open(ep.protocol());
acceptor.set_option(acceptor::reuse_address(true));
acceptor.bind(ep);
acceptor.listen();
L'accepteur est fermé par:
acceptor.close();
J'ai aussi essayé d'utiliser accepteur.annuler() avant, mais il a eu le même effet. Lorsque cette erreur s'est produite, je ne peux pas redémarrer le serveur sur le même port, pour un certain temps. Le redémarrage du réseau d'aide, mais n'est pas une solution permanente.
Ce qui me manque?
Toute aide serait grandement appréciée! 🙂
aussi, êtes-vous sûr que le socket est en état TIME_WAIT? Vous pourriez vouloir prendre le
netstat -ap
de sortie lorsque cela se produit.Sam, je vous remercie beaucoup pour votre participation! Il m'a aidé à trouver la solution à mon problème. Il s'est avéré que je n'ai mis la réutilisation option d'adresse de l'accepteur, mais pas pour toutes les autres connexions. Encore une fois, merci beaucoup pour votre aide!
J'ai ajouté mes commentaires comme une réponse.
OriginalL'auteur Alexander | 2010-11-16
Vous devez vous connecter pour publier un commentaire.
Elles ont été à l'origine d'un commentaire à la question.
votre serveur fourche processus enfants? Aussi, êtes-vous sûr que le socket est en état TIME_WAIT? Vous pourriez vouloir prendre le
netstat -ap
de sortie lorsque cela se produitOriginalL'auteur
Lorsque vous résoudre ces problèmes "par la force", il semble que vous appelez des problèmes sur votre tête, n'est-ce pas?
Il y a une raison pour laquelle le comportement par défaut vous oblige à attendre, sinon le réseau pourrait, par exemple, confondre l'accusé de réception de la précédente connexion à être accusé de réception pour la nouvelle connexion.
Je ne voudrais pas permettre à cette "solution" pour être inclus dans les versions release dans mon équipe.
Rappelez-vous, lorsque la probabilité d'erreur est très faible, le test est extrêmement difficile!
Puis, j'ai commencé sur le serveur. Toutefois, le serveur n'a pas pu commencer à l'écoute sur le même port, car les clients des connexions n'ont pas la réutilisation de l'option et le port était encore réservée. La question maintenant est de savoir comment je peux réutiliser une adresse qui est d'ores et déjà en cours d'utilisation par le système d'exploitation même si toutes les connexions ont été fermé correctement sans l'aide de la réutilisation de l'option?
Juste accepter d'attente (qui peut être assez long) n'est pas une solution acceptable pour un serveur. J'ai cru (et croient encore) que la définition de la réutilisation option est appropriée dans ce cas. Cependant, je suis très intéressé par une solution alternative et serait heureux si vous pouvez fournir ou allusion à un. (Sur une note de côté: La solution proposée ci-dessus fonctionne très bien. Nous utilisons le serveur de manière approfondie et n'a pas de rencontrer des problèmes liés aux connexions. Bien sûr, cela ne garantit pas qu'il est 100% exempt d'erreur.)
Le
FIN_WAIT
délai d'attente est personnalisable; c'est une pratique courante pour réduire la valeur par défaut de 120 secondes, 5 secondes. Cela ne va pas résoudre le problème complètement, vous devez poignée "l'adresse est déjà en cours d'utilisation" de la situation (comme il l'a d'autres raisons valables de se produire) — mais élimine la nécessité pour lesSO_REUSEADDR
.OriginalL'auteur