1
votes

socket.sock (). bind () Adresse déjà utilisée

J'essaie de créer un modèle simple serveur-client pour effectuer la tâche de transfert de fichiers. Mon server.py et client.py ressemblent à ceci:

python3 ./some_path/server.py &
python3 ./some_path/client.py $n
<Client.py>
import socket
import time

time.sleep(3)

s = socket.socket()
host = "ubuntu"
port = 1717
s.connect((host, port))
print("Connected ....")

filename = "My file name"
file = open(filename, 'wb')
file_data = s.recv(2048)
file.write(file_data)
file.close()
print("File has been received.")

En outre, j'ai écrit un fichier shell pour exécuter le serveur et le client, car je ne peux obtenir que pas d'erreur si le serveur tourne avant le client, j'ai écrit dans mon script shell quelque chose comme ceci:

<Server.py>
import socket

s = socket.socket()
host = socket.gethostname()
port = 1717
s.bind((host, port))
s.listen(1)
print(host)
print("Waiting for the client ...")

conn, addr = s.accept()
print(addr, "Connected!")

filename = "My file name"
file = open(filename, 'rb')
file_data = file.read(2048)
conn.send(file_data)
print("File has been sent to server.")
s.close()

Notez que j'ai également ajouté time.sleep (3) au début de mon Client.py parce que j'ai trouvé la commande de script shell que j'ai écrite ne garantit pas que le serveur s'exécute en premier. Maintenant, ce problème est résolu, cependant, j'obtiens l'erreur «Adresse déjà utilisée» à cause de s.bind () dans le server.py chaque fois que je veux exécuter le tout pour la deuxième fois. Cela dit, si j'ouvre mon Ubuntu et exécute le script shell, cela a fonctionné et tout va bien comme prévu. Mais quand c'est fait et que je veux exécuter à nouveau, j'obtiens le "Adresse déjà utilisée".

Mes questions sont donc:

  1. Comment résoudre ce problème, afin que je teste les fonctionnalités sans redémarrer tout l'ordinateur.

  2. Existe-t-il des moyens plus sophistiqués pour obtenir le nom d'hôte au lieu de le spécifier à l'avance? Comme vous pouvez le voir sur client.py, j'ai essentiellement défini l'hôte sur "ubuntu" car c'est ce que j'obtiens si j'imprime le nom d'hôte du côté serveur.

Merci beaucoup d'avoir lu ces longues questions ... Je veux juste rendre les choses plus claires ... J'apprécie beaucoup si vous pouvez répondre à l'une de mes questions ou même donner quelques suggestions. Au fait, je teste tout cela sur une machine ubuntu 14.04.


2 commentaires

Vous devez définir SO_REUSEADDR sur le socket d'écoute avant de le lier.


Cela a vraiment aidé! Merci.


3 Réponses :


0
votes
  1. Essayez de redémarrer entièrement le système. Cela peut signifier que le processus est toujours en cours d'exécution.

0 commentaires

1
votes

Tout d'abord, vous devez également fermer le socket dans le client. Deuxièmement, vous devez appeler shutdown avant de fermer le socket.

Veuillez consulter ce https://stackoverflow.com/a/598759/6625498


1 commentaires

Vous n'avez pas besoin d'appeler shutdown () avant de fermer le socket, et votre lien ne dit pas le contraire.



0
votes
  1. Comment résoudre ce problème, afin que je teste les fonctionnalités sans redémarrer tout l'ordinateur.

    Veuillez exécuter cette commande sur le script shell si vous obtenez le message "Adresse déjà utilisée"

    sudo killall -9 python3

    Et puis exécutez votre serveur et votre client.

  2. Existe-t-il un moyen plus sophistiqué de faire en sorte que client.py s'exécute toujours après la méthode server.py que ma méthode time.sleep ()

  3. Veuillez utiliser ces codes.

    server.py

    import socket
    import time
    from common.constant import *
    from threading import Thread
    import binascii
    from .packet import *
    import threading
    
    
    def recv_msg(sock):
        while True:
            try:
                res = sock.recv(buf_size)
                if not res:
                    continue
                buffer = str(binascii.hexlify(res))
                buffer = [buffer[i:i + 2] for i in range(2, len(buffer) - 1, 2)]
    
                #packet parsing, you maybe change this part.
                packet_parsing(buffer)
                time.sleep(0.100)
            except socket.error:
                print(str(socket.error))
                break
    
    class history_thread(threading.Thread):
        def __init__(self, threadID, name, delay, server, port):
            threading.Thread.__init__(self)
            self.threadID = threadID
            self.name = name
            self.delay = delay
            self.server = server
            self.port = port
            self.sock = None
        def run(self):
            print("Starting " + self.name)
    
            while True:
                try:
                    self.sock = socket.socket()
                    self.sock.connect((self.server, self.port))
    
                    tc = Thread(target=recv_msg, args=(self.sock,))
                    tc.start()
                    threads = []
                    threads.append(tc)
                    for pip in threads:
                        pip.join()
                    self.sock.close()
                    self.sock = None
                except socket.error:
                    print(str(socket.error))
                    if self.sock is not None:
                        self.sock.close()
                    self.sock = None
                time.sleep(self.delay)
    
        def send(self, data):
            if self.sock is None:
                return -1
            try:
                self.sock.sendall(data)
            except:
                print(str(socket.error))
    

    main.py

    his_server = server.server(sever_host, sever_port)
    his_server.onConnected = server.onConnected
    his_server.onDisconnected = server.onDisconnected
    his_server.onData = server.onData
    

    client.py

    import socket
    import threading
    import socketserver
    
    socketserver.TCPServer.allow_reuse_address = True
    
    __all__ = ['server']
    
    
    class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
        def handle(self):
            cur_thread = threading.current_thread()
            requests = self.server.requests
            if self.request not in requests:
                requests[self.request] = {'client_id': cur_thread.ident,
                                          'client_address': self.client_address[0],
                                          'client_port': self.client_address[1]}
    
                if callable(self.server.onConnected):
                    self.server.onConnected(self.request, self.server)
            while True:
                try:
                    buffer = self.request.recv(my_constant.MSG_MAX_SIZE)
                    if not buffer:
                        break
                    buffer = str(binascii.hexlify(buffer))
                    buffer = [buffer[i:i + 2] for i in range(2, len(buffer) - 1, 2)]
    
                    self.server.onData(buffer, self.server, self.request) # process receive function
                except socket.error:
                    print(str(socket.error))
                    break
            if callable(self.server.onDisconnected) and (self.request in requests):
                self.server.onDisconnected(self.request, self.server)
            self.request.close()
    
    
    class server(socketserver.ThreadingTCPServer):
        def __init__(self, host='', port=16838, *args, **kwargs):
            socketserver.ThreadingTCPServer.__init__(self, (host, port), ThreadedTCPRequestHandler)
            self.requests = {}
            self.server_thread = threading.Thread(target=self.serve_forever)
            self.server_thread.setDaemon(True)
            self.server_thread.start()
            self.onConnected = None
            self.onDisconnected = None
            self.onData = None
    
        def stop(self):
            self.quote_send_thread_stop = True
    
            for request in list(self.requests):
                self.shutdown_request(request)
                if self.onDisconnected:
                    self.onDisconnected(request, self)
            self.shutdown()
            self.server_close()
    
        def broadcast(self, data):
            for request in list(self.requests):
                try:
                    request.sendall(data)
                except socket.error:
                    print(str(socket.error))
                    del self.requests[request]
    
        def send(self, request, data):
            try:
                request.sendall(data)
            except socket.error:
                print(str(socket.error))
                del self.requests[request]
    
        def sendRaw(self, client_id, data):
            pass
    
        def disconnect(self, client_id):
            for request in list(self.requests):
                if client_id == self.requests[request]['client_id']:
                    self.shutdown_request(request)
                    if self.onDisconnected:
                        self.onDisconnected(request, self)
                    else:
                        del self.requests[request]
    
    def onConnected(request, server):
        try:
            print('[onConnected] client_address: ' + str(server.requests[request]))
        except Exception as e:
            print(str(e))
    
    def onDisconnected(request, server):
        try:
            print('[onDisconnected] client_address: ' + str(server.requests[request]))
            del server.requests[request]
        except Exception as e:
            print(str(e))
    def onData(request, server):
        #define your process message
        pass
    

4 commentaires

Il n'est pas nécessaire de tuer tous les processus Python 3 dans tout le système d'exploitation pour résoudre «l'adresse déjà utilisée», et en fait cela peut ne pas être suffisant non plus.


Je veux dire que c'est nécessaire dans son code, Et puis s'il vous plaît vérifier mon code serveur.Dans mon code serveur, vous trouverez le drapeau allow_reuse_address.Je ne sais pas pourquoi vous réduisez ma réputation.


Cela n'est nécessaire dans aucun code, et en particulier si vous avez défini allow_reuse_address . Vous ne savez pas qui a «réduit votre réputation».


Tu ne me comprends pas. dans son cas, afin de résoudre son problème dès que possible sans redémarrer l'hôte, ma suggestion est un bon moyen pour lui.