我正在尝试构建一个简单的服务器-客户端模型来执行文件传输任务。我的server.py和client.py看起来像这样:
<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()
<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.")
此外,我还编写了一个运行服务器和客户端的外壳文件,因为如果服务器在客户端之前运行,我只会报错,我在外壳脚本中这样写:
python3 ./some_path/server.py &
python3 ./some_path/client.py $n
注意,我也在Client.py的开头添加了time.sleep(3),因为我发现编写的shell脚本命令不能保证服务器先运行。现在,此问题已解决,但是,由于每次我想第二次运行整个程序时,由于server.py中的s.bind(),我收到了“已经在使用地址”错误。就是说,如果我打开Ubuntu并运行shell脚本,它就可以正常工作,并且一切都按预期进行。但是,当它完成并且我想再次运行时,我会得到“地址已经在使用中”。
所以我的问题是:
如何解决此问题,以便在不重新启动整个计算机的情况下测试功能。
有没有比我的time.sleep()方法更复杂的方法来使client.py始终在server.py之后运行?
还有其他更复杂的方法来获取主机名而不是预先指定吗?从client.py中可以看到,我基本上将主机设置为“ ubuntu”,因为这是从服务器端打印主机名时得到的。
非常感谢您阅读这个冗长的问题...我只是想让事情变得更清楚...非常感谢您能回答我的任何一个问题,甚至提出一些建议。顺便说一下,我正在ubuntu 14.04机器上测试所有这些。
首先,您还需要关闭客户端中的套接字。其次,您应该在关闭套接字之前调用shutdown。
如何解决此问题,以便在不重新启动整个计算机的情况下测试功能。
如果收到此消息“地址已在使用中,请在shell脚本上运行此命令”
sudo killall -9 python3
然后运行服务器和客户端。
有没有比我的time.sleep()方法更复杂的方法来使client.py总是在server.py之后运行?
请使用此代码。
server.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
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 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))