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:
Comment résoudre ce problème, afin que je teste les fonctionnalités sans redémarrer tout l'ordinateur.
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.
3 Réponses :
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
Vous n'avez pas besoin d'appeler shutdown ()
avant de fermer le socket, et votre lien ne dit pas le contraire.
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.
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 ()
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
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.
Vous devez définir SO_REUSEADDR sur le socket d'écoute avant de le lier.
Cela a vraiment aidé! Merci.