web-dev-qa-db-fra.com

Comment fermer une socket laissée ouverte par un programme tué?

J'ai une application Python qui ouvre une simple socket TCP pour communiquer avec une autre application Python sur un hôte séparé. Parfois le programme provoquera une erreur ou je le tuerai directement, et dans les deux cas, le socket peut être laissé ouvert pendant un temps inconnu.

La prochaine fois que je vais exécuter le programme, j'obtiens cette erreur:

socket.error: [Errno 98] Address already in use

Maintenant, le programme essaie toujours d'utiliser le même port, il apparaît donc comme s'il était toujours ouvert. J'ai vérifié et je suis sûr que le programme ne fonctionne pas en arrière-plan et pourtant mon adresse est toujours utilisée.

Alors, comment puis-je fermer manuellement (ou autrement) une socket/adresse afin que mon programme puisse la réutiliser immédiatement?

Mise à jour

Sur la base de la réponse de Mike, j'ai vérifié la page socket(7) et regardé SO_REUSEADDR:

SO_REUSEADDR
    Indicates that the rules used in validating addresses supplied in a bind(2) call should
    allow reuse of local addresses.  For AF_INET sockets this means that a socket may bind,
    except when there is an active listening socket bound to the address.  When the listen‐
    ing  socket is bound to INADDR_ANY with a specific port then it is not possible to bind
    to this port for any local address.  Argument is an integer boolean flag.
37
Mr. Shickadance

Supposons que votre socket s'appelle s... vous devez définir socket.SO_REUSEADDR sur le socket du serveur avant de se lier à une interface ... cela vous permettra de redémarrer immédiatement un serveur TCP ...

s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ADDR, PORT))
37
Mike Pennington

Vous voudrez peut-être essayer d'utiliser Twisted pour votre réseau. Mike a donné la bonne réponse de bas niveau, SO_REUSEADDR, mais il n'a pas mentionné que ce n'était pas une très bonne option à configurer sur Windows. C'est le genre de chose dont Twisted s'occupe automatiquement pour vous. Il existe de très nombreux autres exemples de ce type de détails de bas niveau ennuyeux auxquels vous devez faire attention lorsque vous utilisez directement le module de socket, mais que vous pouvez oublier si vous utilisez une bibliothèque de niveau supérieur comme Twisted.

11

Vous confondez les sockets, les connexions et les ports. Les sockets sont des points de terminaison de connexions, qui sont à leur tour 5-tuples {protocole, local-ip, local-port, remote-ip, remote-port}. Le socket du programme tué a été fermé par le système d'exploitation et idem pour la connexion. La seule relique de la connexion est la prise du pair et le port correspondant sur l'hôte du pair. Donc, ce que vous devriez vraiment demander, c'est comment réutiliser le local port. Pour lequel la réponse est SO_REUSEADDR selon les autres réponses.

5
user207421