Python 写一个简单的FTPv2

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

client code:

#Author :ywq
import socket,os,json,sys
import threading
import time

msg_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 :ywq
import socketserver,sys,os,json


client_dic={}
def dic_init(username,password):
    client_dic[username]={}
    client_dic[username]['file_list']=[]
    client_dic[username]['Username']=username
    client_dic[username]['Password']=password

dic_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_info

def 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',999
server=socketserver.ThreadingTCPServer((IP,Port),MyHandler)
print('\033[1;32mWaiting for connection:\033[0m')
server.serve_forever()


运行效果:

这里写图片描述

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值