111 votes

Python: Liaison de socket: "Adresse déjà utilisée"

J'ai une question concernant le socket client sur un réseau TCP/IP. Disons que j'utilise

try:

    comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

except socket.error, msg:

    sys.stderr.write("[ERROR] %s\n" % msg[1])
    sys.exit(1)

try:
    comSocket.bind(('', 5555))

    comSocket.connect()

except socket.error, msg:

    sys.stderr.write("[ERROR] %s\n" % msg[1])

    sys.exit(2)

Le socket créé sera lié au port 5555. Le problème est qu'après la fin de la connexion

comSocket.shutdown(1)
comSocket.close()

En utilisant Wireshark, je vois que le socket est fermé avec FIN, ACK et ACK des deux côtés, je ne peux pas réutiliser le port. Je reçois l'erreur suivante:

[ERROR] Address already in use

Je me demande comment je peux libérer le port immédiatement pour pouvoir l'utiliser la prochaine fois.

comSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

setsockopt ne semble pas pouvoir résoudre le problème Merci!

4voto

Maurice Flanagan Points 2950

Comme mentionné par Felipe Cruze, vous devez définir le SO_REUSEADDR avant la liaison. J'ai trouvé une solution sur un autre site - solution sur un other site, reproduced below

Le problème est que l'option de socket SO_REUSEADDR doit être définie avant que l'adresse ne soit liée au socket. Cela peut être fait en sous-classant ThreadingTCPServer et en remplacant la méthode server_bind comme suit :

import SocketServer, socket

class MyThreadingTCPServer(SocketServer.ThreadingTCPServer):
    def server\_bind(self):
        self.socket.setsockopt(socket.SOL\_SOCKET, socket.SO\_REUSEADDR, 1)
        self.socket.bind(self.server\_address)

3voto

peets Points 141

J'ai trouvé une autre raison pour cette exception. Lorsque l'application est exécutée à partir de l'IDE Spyder (dans mon cas, il s'agissait de Spyder3 sur Raspbian) et que le programme se termine par ^C ou une exception, le socket était toujours actif :

sudo netstat -ap | grep 31416
tcp  0  0 0.0.0.0:31416  0.0.0.0:*    LISTEN      13210/python3

En exécutant à nouveau le programme, j'ai rencontré l'erreur "Adresse déjà utilisée"; l'IDE semble démarrer le nouveau 'run' en tant que processus séparé qui trouve le socket utilisé par le 'run' précédent.

socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

n'a PAS aidé.

Tuer le processus 13210 a aidé. Démarrer le script python à partir de la ligne de commande comme

python3 .py

a toujours bien fonctionné lorsque SO_REUSEADDR était défini sur true. Le nouvel IDE Thonny ou l'IDE Idle3 n'avaient pas ce problème.

1voto

Felipe Cruz Points 628

socket.socket() doit s'exécuter avant socket.bind() et utiliser REUSEADDR comme indiqué

1voto

jcoffland Points 1506

Je sais que vous avez déjà accepté une réponse mais je crois que le problème a à voir avec l'appel à bind () sur un socket client. Cela peut aller mais bind () et shutdown () ne semblent pas bien fonctionner ensemble. De plus, SO_REUSEADDR est généralement utilisé avec les sockets d'écoute. c'est-à-dire du côté serveur.

Vous devriez passer une adresse IP / port à connect (). Comme ceci:

comSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
comSocket.connect(('', 5555))

Ne pas appeler bind (), ne pas définir SO_REUSEADDR.

1voto

user2455528 Points 11

Pour moi, la meilleure solution était la suivante. Puisque l'initiative de fermer la connexion venait du serveur, le setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) n'avait aucun effet et le TIME_WAIT empêchait une nouvelle connexion sur le même port avec l'erreur :

[Errno 10048]: Address already in use. Only one usage of each socket address (protocol/IP address/port) is normally permitted

J'ai finalement utilisé la solution de laisser le système d'exploitation choisir le port lui-même, puis un autre port est utilisé si le précédent est toujours en TIME_WAIT.

J'ai remplacé :

self._socket.bind((invité, port))

par :

self._socket.bind((invité, 0))

Comme cela était indiqué dans la documentation sur les sockets en python d'une adresse tcp :

Si elle est fournie, source_address doit être un 2-uplet (hôte, port) pour le socket à lier en tant qu'adresse source avant de se connecter. Si hôte ou port sont ‘’ ou 0 respectivement, le comportement par défaut du système d'exploitation sera utilisé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X