基于python标准库socket流和结构体struct的ftp文件上传和下载
1 目录
说明下:文件上传成功,但是pycharm没显示文件,需要刷新,其实桌面文件夹upload里面早就有了
2 先启动的服务端
import socket import struct import json import os base_path = os.path.dirname(os.path.abspath(__file__)) class MYTCPServer: address_family = socket.AF_INET socket_type = socket.SOCK_STREAM allow_reuse_address = True max_packet_size = 8192 coding = 'utf-8' request_queue_size = 5 #上传文件地址 server_dir = os.path.join(base_path, 'upload') print(server_dir) def __init__(self, server_address, bind_and_listen=True): """Constructor. May be extended, do not override.""" self.server_address = server_address self.socket = socket.socket(self.address_family, self.socket_type) if bind_and_listen: try: self.server_bind() self.server_listen() except: self.server_close() raise def server_bind(self): """Called by constructor to bind the socket. """ if self.allow_reuse_address: self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.bind(self.server_address) self.server_address = self.socket.getsockname() def server_listen(self): """Called by constructor to activate the server. """ self.socket.listen(self.request_queue_size) def server_close(self): """Called to clean-up the server. """ self.socket.close() def get_request(self): """Get the request and client address from the socket. """ return self.socket.accept() def close_request(self, request): """Called to clean up an individual request.""" request.close() def run(self): while True: self.conn, self.client_addr = self.get_request() print('from client ', self.client_addr) while True: try: head_struct = self.conn.recv(4) if not head_struct: break head_len = struct.unpack('i', head_struct)[0] head_content = self.conn.recv(head_len).decode(self.coding) head_data = json.loads(head_content) print(head_data) #head_data={'cmd':'put','filename':'a.txt','filesize':123123} cmd = head_data['cmd'] if hasattr(self, cmd): func = getattr(self, cmd) func(head_data) except Exception: break def put(self, args): file_path = os.path.normpath(os.path.join(self.server_dir, args['filename'])) filesize = args['filesize'] recv_size = 0 print('file_path----->', file_path) with open(file_path, 'wb') as f: while recv_size < filesize: recv_data = self.conn.recv(self.max_packet_size) f.write(recv_data) recv_size += len(recv_data) print('recvsize:%s filesize:%s' %(recv_size, filesize)) if __name__ == '__main__': tcpserver = MYTCPServer(('127.0.0.1', 9090)) tcpserver.run()
3 后启动的客户端以及客户端输入download文件夹下的hello.txt文件
import socket import struct import json import os base_path = os.path.dirname(os.path.abspath(__file__)) class MYTCPClient: address_family = socket.AF_INET socket_type = socket.SOCK_STREAM allow_reuse_address = False max_packet_size = 8192 coding = 'utf-8' request_queue_size = 5 def __init__(self, server_address, connect=True): self.server_address = server_address self.socket = socket.socket(self.address_family, self.socket_type) if connect: try: self.client_connect() except: self.client_close() raise def client_connect(self): self.socket.connect(self.server_address) def client_close(self): self.socket.close() def run(self): """example: put /Users/Alex/Desktop/ftp/download/hello.txt""" while True: print("format input:put /Users/Alex/Desktop/ftp/download/hello.txt") cmd_args = input(">>:").strip() if not cmd_args: continue cmd_args_list = cmd_args.split() cmd = cmd_args_list[0] if hasattr(self, cmd): func = getattr(self, cmd) func(cmd_args_list) def put(self, args): cmd = args[0] filename = args[1] if not os.path.isfile(filename): print('file:%s is not exists' %filename) return else: filesize = os.path.getsize(filename) head_dic = {'cmd': cmd, 'filename': os.path.basename(filename), 'filesize': filesize} print(head_dic) head_json = json.dumps(head_dic) head_json_bytes = bytes(head_json, encoding=self.coding) print(head_dic) head_struct = struct.pack('i',len(head_json_bytes)) print("lenth of head_struct:", len(head_struct)) # 4 self.socket.send(head_struct) print("head_struct:", head_struct) self.socket.send(head_json_bytes) print("head_json_bytes:", head_json_bytes) send_size = 0 with open(filename, 'rb') as f: for line in f: self.socket.send(line) send_size += len(line) print(send_size) else: print('upload successful') if __name__ == '__main__': client = MYTCPClient(('127.0.0.1', 9090)) client.run()
4 基本操作
启动服务端和客户端后,在客户端执行:put /Users/Alex/Desktop/ftp/download/hello.txt 具体路径改成你自己的路径