Python 写一个简单的FTPv2

来源:互联网 发布:江西省洪水计算软件 编辑:程序博客网 时间:2024/06/03 14:36

**相较上一篇v1的改进版,当前实现了如下功能:
1.上传
2.下载
3.查看server端保存的文件列表
4.上传、下载显示进度条
5.server端将client信息保存为json格式存入本地,实时加载和写入

client code:

#Author :ywqimport socket,os,json,sysimport threadingimport timemsg_dic={}size_dic={}clac_event=threading.Event()class Scok_Client(object):    def __init__(self):        self.client=socket.socket()    def connect(self,IP,Port):        self.client.connect((IP,Port))    def usage(self):        print(            '''            Usage:action + parameter                Put Filename                Get Filename                Ls                cd ../..            '''        )    def auth(self):        user=input('Input username:')        passwd=input('Input passwd:')        msg_dic['Username']=user        msg_dic['Password']=passwd    def progressbar(self,a,b):        percentage = a/b        num = int(percentage*100)        view = '\r %d%%[%-100s]%d%%'%(0,'#'*num,100)        sys.stdout.write(view)        sys.stdout.flush()    def interactive(self):        while True:            self.auth()            while True:                try:                    cmd_str=input('Input cmd:')                    cmd=cmd_str.split()[0]                    print('Exec action:',cmd )                    if hasattr(self,'cmd_%s' %cmd) :                        act=getattr(self,'cmd_%s' %cmd)                        act(cmd_str)                except Exception as e:                    print('Error:',e)                    self.usage()    def cmd_put(self,*args):        cmd,filename=args[0].split()        if os.path.isfile(filename):            msg_dic['Action']=cmd            msg_dic['Filename']=filename            file_size=os.path.getsize(filename)            msg_dic[filename+'_Filesize']=file_size            print('\033[1;32mSend Info to Server:\033[0m \n',msg_dic)            self.client.send(json.dumps(msg_dic).encode())            server_ack=self.client.recv(8192)            print('Server ACK:',server_ack)            f=open(filename,'rb')            finished_size=0            start_time=time.time()            clac_start_time=start_time            for line in f:                self.client.send(line)                finished_size+=len(line)                while time.time() - start_time >0.5:                    self.progressbar(finished_size,file_size)                    start_time=time.time()   #print percentage every 0.5 second            print('\033[1;31m%s done,use time:%i seconds\033[0m' %(cmd,time.time()-clac_start_time))            f.close()    def cmd_get(self,*args):        cmd,filename=args[0].split()        msg_dic['Action']=cmd        msg_dic['Filename']=filename        self.client.send(json.dumps(msg_dic).encode())        file_size=int(self.client.recv(8192).decode())        print('\033[1;32mGet File,size:\033[0m',file_size)        self.client.send(b'Client ACK')        f=open(filename,'wb')        finished_size=0        while finished_size < file_size:            data=self.client.recv(8192)            f.write(data)            finished_size+=len(data)            self.progressbar(finished_size,file_size)        else:            print('\033[1;32mReceive done\033[0m',os.stat(filename))            f.close()    def cmd_ls(self,*args):        cmd=args[0].split()[0]        msg_dic['Action']=cmd        self.client.send(json.dumps(msg_dic).encode())        file_list=self.client.recv(8192)        print('\033[1;32mMy file list in server:\033[0m',file_list.decode())ftp_client=Scok_Client()ftp_client.connect('localhost',999)ftp_client.interactive()

server code:

#Author :ywqimport socketserver,sys,os,jsonclient_dic={}def dic_init(username,password):    client_dic[username]={}    client_dic[username]['file_list']=[]    client_dic[username]['Username']=username    client_dic[username]['Password']=passworddic_init('ywq','qwe')with open('client_auth.json','w')as auth_conf:    json.dump(client_dic,auth_conf)    '''    save the client auth_info as json_format into local    '''with open('client_auth.json','r+') as auth_conf:    client_dic=json.load(auth_conf)        #load client auth_infodef auth(recv_dic):    client_user=recv_dic['Username']    client_passwd=recv_dic['Password']    if client_user == client_dic[client_user]['Username'] and client_passwd == client_dic[client_user]['Password']:        pass    else:        exit('Auth failed')class MyHandler(socketserver.BaseRequestHandler):    def handle(self):        while True:            try:                recv_dic=json.loads(self.request.recv(8192).decode())                print('\033[1;31mReceive client dic\033[0m\n',recv_dic)                auth(recv_dic)                client_cmd=recv_dic['Action']                if hasattr(self,'client_%s' %client_cmd ):                    exec_cmd=getattr(self,'client_%s' %client_cmd)                    exec_cmd(recv_dic)            except Exception as e:                print('Error:',e)    def client_put(self,*args):        recv_dic=args[0]        client_user=recv_dic['Username']        client_dic[client_user].update(recv_dic)        filename=recv_dic['Filename']        filesize=int(recv_dic[filename+'_Filesize'])        print(filesize)        received_size=0        if os.path.isfile(filename):            print('file is already exist')            exit(2)        else:            f=open(filename,'wb')            self.request.send(b'Server ACK')            while received_size < filesize:                data=self.request.recv(8192)                f.write(data)                received_size+=len(data)            else:                print('\033[1;32m Recv done! \033[0m',os.stat(filename))                f.close()                client_dic[client_user]['file_list'].append(filename)                print(client_dic[client_user]['file_list'])                with open('client_auth.json','r+') as auth_conf:                    json.dump(client_dic,auth_conf)    def client_get(self,*args):        recv_dic=args[0]        filename=recv_dic['Filename']        file_size=os.stat(filename).st_size  #or os.path.getsize()        self.request.send(str(file_size).encode())   #send file size to client        client_ack=self.request.recv(8192)        f=open(filename,'rb')        for line in f:            self.request.send(line)        print('\033[1;32m Send done ,total size:\033[0m',file_size)        f.close()    def client_ls(self,*args):        recv_dic=args[0]        client_user=recv_dic['Username']        user_file_list=client_dic[client_user]['file_list']        self.request.send(str(user_file_list).encode())        print('\033[1;32m Send file_list to user %s:\033[0m' %client_user)IP,Port='localhost',999server=socketserver.ThreadingTCPServer((IP,Port),MyHandler)print('\033[1;32mWaiting for connection:\033[0m')server.serve_forever()

运行效果:

这里写图片描述

运行完成后的json文件:
这里写图片描述