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!

1voto

test30 Points 359

Une autre solution, en environnement de développement bien sûr, est de tuer le processus en cours en l'utilisant, par exemple

def serve():
    server = HTTPServer(('', NUMERO_DE_PORT), BaseHTTPRequestHandler)
    print 'Serveur http démarré sur le port' , NUMERO_DE_PORT
    server.serve_forever()
try:
    serve()
except Exception, e:
    print "probablement le port est utilisé. tuer les processus utilisant le port donné %d, %s"%(NUMERO_DE_PORT, e)
    os.system("xterm -e 'sudo fuser -kuv %d/tcp'" % NUMERO_DE_PORT)
    serve()
    raise e

0voto

Kiblawi_Rabee Points 174

Je pense que la meilleure façon est simplement de tuer le processus sur ce port, en tapant dans le terminal fuser -k [NUMÉRO DE PORT]/tcp, par exemple fuser -k 5001/tcp.

0voto

Semih Points 33

J'ai eu le même problème et je n'ai pas pu trouver d'autre solution (les options de réutilisation n'ont pas fonctionné) sauf redémarrer le Raspberry Pi à chaque fois. Ensuite, j'ai trouvé une solution de contournement;

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

Cela signifie, définir d'abord socket, le fermer, puis le redéfinir, vous pouvez ainsi utiliser le même port s'il est bloqué.

0voto

CHINMAY JAIN Points 1

Le même problème a été résolu dans Kathiravelu P., Sarker F. - Python Network Programming Cookbook, Deuxième édition - 2017. Ajout ci-dessous le code utile.

    # Réutiliser les adresses de socket

import socket
import sys

def reuse_socket_addr():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # Obtenir l'ancien état de l'option SO_REUSEADDR
    old_state = sock.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
    print("Ancien état de la socket : %s" %old_state)

    # Activer l'option SO_REUSEADDR
    sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    new_state = sock.getsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR)
    print("Nouvel état de la socket : %s" %new_state)

    local_port = 8282
    srv = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)

    srv.bind( ('',local_port) )
    srv.listen(1)
    print("En écoute sur le port : %s" %local_port)

    while True:
        try:
            connection, addr = srv.accept()
            print("Connecté par %s: %s" %(addr[0],addr[1]))
        except KeyboardInterrupt:
            break
        except socket.error as msg:
            print("%s" %(msg,))

if __name__ == "__main__":
    reuse_socket_addr()

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