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.