需求:
- 用户加密认证
- 允许同时多用户登录
- 每个用户有自己的家目录 ,且只能访问自己的家目录
- 对用户进行磁盘配额,每个用户的可用空间不同
- 允许用户在ftp server上随意切换目录
- 允许用户查看当前目录下文件
- 允许上传和下载文件,保证文件一致性
- 文件传输过程中显示进度条
- 附加功能:支持文件的断点续传
client:
#coding:utf-8 import socket import json import os #client.connect(('192.168.16.200',9999)) class FtpClient(object): def __init__(self): self.client = socket.socket() def help(self): msg = ''' ls pwd cd ../.. get filename put filename ''' print(msg) def connect(self,ip,port): self.client.connect((ip, port)) def interactive(self): #self.authenticate() while True: cmd = input(">>").strip() if len(cmd) ==0:continue cmd_str = cmd.split()[0] if hasattr(self,"cmd_%s" % cmd_str): func = getattr(self,"cmd_%s" % cmd_str) func(cmd) else: self.help() def cmd_put(self,*args): cmd_split = args[0].split() if len(cmd_split) >1: filename = cmd_split[1] if os.path.isfile(filename): filesize = os.stat(filename).st_size msg_dic = { "action": "put", "filename":filename, "size": filesize, "overridden":True } self.client.send( json.dumps(msg_dic).encode("utf-8") ) print("send",json.dumps(msg_dic).encode("utf-8") ) #防止粘包,等服务器确认 server_response = self.client.recv(1024) f = open(filename,"rb") for line in f: self.client.send(line) else: print("file upload success...") f.close() else: print(filename,"is not exist") def cmd_get(self): pass ftp = FtpClient() ftp.connect("localhost",9999) ftp.interactive()
server:
import socketserver import json,os class MyTCPHandler(socketserver.BaseRequestHandler): def put(self,*args): '''接收客户端文件''' cmd_dic = args[0] filename = cmd_dic["filename"] filesize = cmd_dic["size"] if os.path.isfile(filename): f = open(filename + ".new","wb") else: f = open(filename , "wb") self.request.send(b"200 ok") received_size = 0 while received_size < filesize: data = self.request.recv(1024) f.write(data) received_size += len(data) else: print("file [%s] has uploaded..." % filename) def handle(self): while True: try: self.data = self.request.recv(1024).strip() print("{} wrote:".format(self.client_address[0])) print(self.data) cmd_dic = json.loads(self.data.decode()) action = cmd_dic["action"] if hasattr(self,action): func = getattr(self,action) func(cmd_dic) except ConnectionResetError as e: print("err",e) break if __name__ == "__main__": HOST, PORT = "localhost", 9999 # Create the server, binding to localhost on port 9999 server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) server.serve_forever()