2010-11-16 6 views
10

J'ai écrit un serveur qui écoute les connexions TCP entrantes et les clients qui s'y connectent. Lorsque j'arrête le serveur et le redémarre sur le même port, il m'arrive d'obtenir le message d'erreur EADDRINUSE lors de l'appel de bind (...) (code d'erreur: 98 sous Linux). Cela se produit même si je définis l'option pour réutiliser le socket.Adresse déjà utilisée avec boost asio acceptor

L'erreur ne se produit pas tout le temps, mais il semble que cela arrive plus souvent lorsque les clients sont connectés au serveur et qu'ils envoient des données pendant l'arrêt. Je suppose que le problème est qu'il existe toujours des connexions en attente lorsque le serveur est arrêté (sujet connexe: https://stackoverflow.com/questions/41602/how-to-forcibly-close-a-socket-in-time-wait). Côté serveur, j'utilise boost :: asio :: ip :: tcp :: acceptor. Je l'initialise 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ée avec:

acceptor.close(); 

J'ai essayé également d'utiliser acceptor.cancel() avant, mais il avait le même effet. Lorsque cette erreur s'est produite, je ne peux pas redémarrer le serveur sur le même port pendant un certain temps. Redémarrer le réseau aide, mais n'est pas une solution permanente.

Qu'est-ce qui me manque?

Toute aide serait grandement appréciée! :)

+1

votre serveur fork fork traite-t-il? –

+1

également, êtes-vous sûr que le socket est dans l'état TIME_WAIT? Vous pourriez vouloir saisir la sortie 'netstat -ap' quand cela arrive. –

+1

Sam, merci beaucoup pour votre contribution! Cela m'a aidé à trouver la solution à mon problème. Il s'est avéré que j'ai défini l'option d'adresse de réutilisation pour l'accepteur, mais pas pour toutes les autres connexions. Encore une fois, merci beaucoup pour votre aide! – Alexander

Répondre

1

C'étaient à l'origine un commentaire à la question.


votre serveur fork fork traite-t-il? Aussi, êtes-vous sûr que le socket est dans l'état TIME_WAIT? Vous pouvez saisir la sortie netstat -ap lorsque cela se produit

0

Lorsque vous résolvez 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 le ACK de la connexion précédente avec ACK pour la nouvelle connexion.

Je ne permettrais pas que cette "solution" soit incluse dans les versions de version de mon équipe. Rappelez-vous, lorsque la probabilité d'erreur est très faible, le test est extrêmement difficile!

+0

Merci pour votre réponse. J'ai divisé ma réponse en raison des limitations d'espace. Je récapitule d'abord la situation: Un serveur était en cours d'exécution et écouté sur un port fixe pour les connexions entrantes. Ensuite, les clients s'y sont connectés sur ce port. À un certain moment, j'ai arrêté le serveur, ce qui a conduit tous les clients à fermer leur connexion au serveur. (Je suis assez sûr que j'ai fermé correctement les connexions côté serveur et côté client.) – Alexander

+0

Ensuite, j'ai redémarré le serveur. Cependant, le serveur n'a pas pu commencer à écouter sur le même port car les connexions des clients n'avaient pas l'option de réutilisation et le port était toujours réservé.La question est maintenant comment je peux réutiliser une adresse qui est déjà marquée en cours d'utilisation par le système d'exploitation même si toutes les connexions ont été fermées correctement sans utiliser l'option de réutilisation? – Alexander

+3

Accepter simplement d'attendre (ce qui peut prendre du temps) n'est pas une solution acceptable pour un serveur. Je croyais (et je crois toujours) que la définition de l'option de réutilisation est appropriée dans ce cas. Cependant, je suis très intéressé par une solution alternative et serais heureux si vous pouviez fournir ou faire allusion à un. (Remarque: La solution proposée ci-dessus fonctionne très bien, nous utilisons beaucoup le serveur et nous n'avons rencontré aucun problème lié aux connexions, ce qui ne garantit évidemment pas 100% d'erreur.) – Alexander

Questions connexes