server
import os import socket import time import selectors BASE_DIR = os.path.dirname(os.path.abspath(__file__)) class selectFtpServer(object): def __init__(self): self.dic = {} self.hasReceived = 0 self.sel = selectors.DefaultSelector() self.create_socket() self.handler() def create_socket(self): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind(("127.0.0.1", 8885)) server.listen(5) self.sel.register(server, selectors.EVENT_READ, self.accept) print("服务端已开启,等待用户连接...") def handler(self): while True: events = self.sel.select() for key, mask in events: call_back = key.data call_back(key.fileobj, mask) def accept(self, server, mask): conn, addr = server.accept() print("from %s %s connected" % addr) self.sel.register(conn, selectors.EVENT_READ, self.read) self.dic[conn] = {} def read(self, conn, mask): try: if not self.dic[conn]: data = conn.recv(1024) cmd, filename, filesize = str( data, encoding='utf-8').split('|') self.dic = { conn: { "cmd": cmd, "filename": filename, "filesize": int(filesize)}} print(self.dic) if cmd == 'put': conn.send(bytes("OK", encoding='utf8')) if self.dic[conn]['cmd'] == 'get': file = os.path.join(BASE_DIR, "download", filename) if os.path.exists(file): fileSize = os.path.getsize(file) send_info = '%s|%s' % ('YES', fileSize) conn.send(bytes(send_info, encoding='utf8')) else: send_info = '%s|%s' % ('NO', 0) conn.send(bytes(send_info, encoding='utf8')) else: if self.dic[conn].get('cmd', None): print(self.dic[conn].get('cmd')) cmd = self.dic[conn].get('cmd') print(cmd) if hasattr(self, cmd): func = getattr(self, cmd) func(conn) else: print("error cmd!") conn.close() else: print("error cmd!") conn.close() except Exception as e: print('error', e) self.sel.unregister(conn) conn.close() def put(self, conn): self.hasReceived = 0 fileName = self.dic[conn]['filename'] fileSize = self.dic[conn]['filesize'] path = os.path.join(BASE_DIR, "upload", fileName) while self.hasReceived < fileSize: recv_data = conn.recv(1024) self.hasReceived += len(recv_data) with open(path, 'wb') as f: f.write(recv_data) if fileSize == self.hasReceived: if conn in self.dic.keys(): self.dic[conn] = {} print("%s上传完毕!" % fileName) def get(self, conn): filename = self.dic[conn]['filename'] path = os.path.join(BASE_DIR, "download", filename) if str(conn.recv(1024), 'utf-8') == "second_active": with open(path, 'rb') as f: for line in f: conn.send(line) self.dic[conn] = {} print('文件下载完毕!') if __name__ == '__main__': ftp = selectFtpServer()
client
import socket import time import os BASE_DIR = os.path.dirname(os.path.abspath(__file__)) class selectFtpClient(): def __init__(self): self.createSocket() self.command_out() def createSocket(self): try: self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client.connect(("127.0.0.1", 8885)) print('连接FTP服务器成功!') except Exception as e: print("error: ", e) def command_out(self): while True: cmd = input('>>>').strip() if cmd == 'exit': break cmd, file = cmd.split() if hasattr(self, cmd): func = getattr(self, cmd) func(cmd, file) else: print('调用错误!') def get(self, cmd, file): pass def put(self, cmd, file): if os.path.isfile(file): fileName = os.path.basename(file) fileSize = os.path.getsize(file) fileInfo = '%s|%s|%s' % (cmd, fileName, fileSize) self.client.send(bytes(fileInfo, encoding='utf8')) recvStatus = self.client.recv(1024) print('recvStatus', recvStatus) hasSend = 0 if str(recvStatus, encoding='utf8') == "OK": with open(file, 'rb') as f: while fileSize > hasSend: contant = f.read(1024) recv_size = len(contant) self.client.send(contant) hasSend += recv_size s = str(int(hasSend / fileSize * 100)) + "%" print("正在上传文件:" + fileName + " 已经上传:" + s) print('%s文件上传完毕' % (fileName,)) else: print('文件不存在') if __name__ == '__main__': c = selectFtpClient()