python 学习分享-实战篇高级的ftp

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 学习分享-实战篇高级的ftp相关的知识,希望对你有一定的参考价值。

#server代码
import socketserver,os,hashlib

Base_paht = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + /db

class Server_ftp(socketserver.BaseRequestHandler):
    def handle(self):
        while 1:
            try:
                self.username = self.request.recv(1024).strip()          #接受用户信息
                if not self.username:continue
                self.username_path = Base_paht + /%s/ % self.username.decode()   #获取用户文件地址
                print(self.username.decode(), 连接成功!)              #打印用户连接信息
                self.request.send(连接服务器成功!.encode())
                while 1:
                    try:
                        self.data = self.request.recv(1024).strip()  #接受客户端命令
                        print(-->,self.data)
                        if not self.data :continue
                        print({} wrote:.format(self.client_address[0]),self.username)#打印ip及用户名称
                        cmd_dic = self.data.decode()   #命令编码
                        print(执行的命令为,cmd_dic)
                        if hasattr(self,cmd_dic + _file):   #判断是否存在这条命令
                            self.request.send({}命令可以被执行.format(cmd_dic).encode())
                            func = getattr(self,cmd_dic + _file)    #反射
                            func()
                        else:
                            self.request.send(no.encode())  #不存在发送错误信息
                    except ConnectionResetError as e:
                      #  print(‘err‘,e)
                        break
            except ConnectionResetError as e:
                print(self.client_address[0],e)
                break
    def get_file(self):
        filename = self.request.recv(1024).decode()
        print(客户端想要获取的文件名称为:,filename)
        if os.path.isfile(self.username_path + filename) :
            file_size = os.stat(self.username_path + filename).st_size  #确认文件大小
            self.request.send(str(file_size).encode())   #发送文件大小
            self.request.recv(1024)  #接收please give me
            f = open(self.username_path + filename,rb)
            self.request.send(f.read())
            f.close()
            confirm = self.request.recv(1024).decode()
            print(confirm)
            f_1 = open(self.username_path + filename, rb)
            m2 = hashlib.md5()
            m2.update(f_1.read())
            f_1_m2 = m2.hexdigest()
            f.close()
            self.request.send(f_1_m2.encode())
            print(self.request.recv(1024).decode())


        else:
            self.request.send(no.encode())   #如果文件不存在,发送no信息
    def put_file(self):
        filename = self.request.recv(1024).decode()
        if filename != no :
            self.request.send(服务器收到文件名称!.encode())
            file_size = self.request.recv(1024).decode()
            self.request.send(服务器收到文件大小为{}.format(file_size).encode())
            f = open(self.username_path + filename,wb)   #直接写入,如果有就覆盖
            confirm_size = 0
            while confirm_size < int(file_size):
                if int(file_size) - confirm_size > 1024:  # 确保接受的准确性,拒绝粘包.
                    cal = 1024
                else:
                    cal = int(file_size) - confirm_size
                data = self.request.recv(cal)
                confirm_size += len(data)
                f.write(data)
            f.close()
            f_1 = open(self.username_path + filename,rb)
            m2 = hashlib.md5()
            m2.update(f_1.read())
            f_1_m2 = m2.hexdigest()
            f_1.close()
            self.request.send(f_1_m2.encode())
            print(self.request.recv(1024).decode())
            self.request.send({}上传完成.format(filename).encode())  # 返回服务器信息,表示下载完成

        else:
            print(客户端传送错误文件名称!)


    def open_file(self):
        filename = self.request.recv(1024).decode()
        self.request.send(服务器收到目录名称!.encode())
        self.request.recv(1024)  #防止粘包
        if os.path.exists(self.username_path + filename ):
            self.request.send(yes.encode())
            self.request.recv(1024)
            path_dir = os.listdir(self.username_path+ filename)
            if path_dir == []:  # 如果为空
                self.request.send(nothing.encode())
            else:
                self.request.send(str(path_dir).encode())
        else:
            self.request.send(no.encode())

    def look_file(self):
        self.request.recv(1024)        #接收返回的数据,防止粘包
        path_dir = os.listdir(self.username_path)
        if path_dir == []:                       #如果为空
            self.request.send(nothing.encode())
        else:
            self.request.send(str(path_dir).encode())





if __name__ ==__main__:
    HOST,PORT = localhost , 6969
    server = socketserver.ThreadingTCPServer((HOST,PORT),Server_ftp)
    print(----------->等待连接<------------)
    server.serve_forever()
#client代码


import socket,os,pickle,hashlib,sys



floder_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + /user_floder
user_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + /conf
server_db_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + /server_ftp/db/


class Scoket_ftp(object):
    # 客户端类
    def __init__(self):
        self.client = socket.socket()

    def client_user_register(self):
        #用户注册
        username = input(请输入用户名:).strip()
        password = input(请输入密码:).strip()
        if not os.path.exists(user_path + /%s%username) :
            pwd_md = hashlib.md5()       #md5加密用户密码
            pwd_md.update(bytes(password,encoding=utf-8))
            pwd_save = pwd_md.hexdigest()
            pickle.dump({username:username,password:pwd_save},open(user_path + /%s%username,wb))
            os.makedirs(server_db_path + username)
            print(创建成功!)
        else:
            print(账户已经存在!)


    def client_user_login(self):
        #身份验证
        username = input(请输入用户名:).strip()
        password = input(请输入密码:).strip()
        if os.path.exists(user_path + /%s%username) :
            pwd_md = hashlib.md5()  # md5加密用户密码
            pwd_md.update(bytes(password,encoding=utf-8))
            pwd_save = pwd_md.hexdigest()
            user_dic = pickle.load(open(user_path + /%s%username,rb))
            if username == user_dic[username] and pwd_save == user_dic[password] :
                print(%s登录成功%username)
                return username
            else:
                print(账户密码错误!)
                return False
        else:
            print(账户密码错误!)
            return False

    def client_conn(self,ip_addr,port):
        #建立连接
        while 1:
            username = self.client_user_login()
            if username :
                self.client.connect((ip_addr, port))
                self.client.send(username.encode())
                print(self.client.recv(1024).decode())
                break
            else:
                continue


    def help(self):
        #帮助信息
        print(‘‘‘
        -----------help-----------
        look:查看当前目录下文件
        open foldername:打开文件夹
        get filename:下载文件
        put filename:上传文件
                ‘‘‘)
    def client_interaction(self):
        #交互
        while 1:
            self.help()
            cmd = input(请输入操作命令:).strip()
            if len(cmd.split()) == 1:  #判断命令行长度,如果是1的话,在判断输入
                if cmd == look:

                    self.file_look()#使用look方法
                elif cmd == exit:
                    self.file_exit()
                else:
                    print(命令输入错误,请重新输入)
                    continue
            elif len(cmd.split()) == 2: #长度为2,证明是带有前面的语句的
                cmd_option, filename = cmd.split()
                if hasattr(self,file_ + cmd_option):
                    func = getattr(self,file_ +cmd_option)
                    func(filename)
                else:
                    continue
            else:
                continue
    def file_look(self):
        #查看
        self.client.send(look.encode()) #发送方法
        print(self.client.recv(1024).decode())  # 服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常
        self.client.send(please give me!.encode())  # 自动发送给服务器
        print(文件目录:,self.client.recv(1024).decode()) #接收目录信息并打印
    def file_get(self,filename):
        #下载
        self.client.send(get.encode())  #先发送方法
        print(self.client.recv(1024).decode())  #服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常
        self.client.send(filename.encode())  #再发送文件名称
        confirm = self.client.recv(1024).decode()  #服务器确认文件是否存在,如果存在返回文件大小,如果不存在,返回no
        if confirm != no:
            self.client.send(please give me!.encode())
            f = open(floder_path+/+filename,wb)  #在下载文件夹中创建该文件(如果存在,则替换)
            confirm_cal = 0
            rate = 1
            while confirm_cal < int(confirm):
                if int(confirm) - confirm_cal > 1024:   #确保接受的准确性,拒绝粘包.
                    cal = 1024
                else:
                    cal = int(confirm) - confirm_cal
                data = self.client.recv(cal)
                confirm_cal += len(data)   #避免tcp拆包
                f.write(data)
                if int(confirm) > 102400:
                    if confirm_cal  > int(confirm)/100*(rate+1) and rate<= 100  :
                        rate += 1
                        r = \r[%s]%d%% % ("=" * rate, rate)
                        sys.stdout.write(r)
                        sys.stdout.flush()
                    else:
                        continue
                else:
                    r = [%s]%d%%%(=*100,100)
                    sys.stdout.write(r)
            f.close()
            self.client.send({}下载完成.format(filename).encode())  # 返回服务器信息,表示下载完成
            f_1 = open(floder_path+/+filename,rb)  #判断一致性
            m2 = hashlib.md5()
            m2.update(f_1.read())
            f_1_m2 = m2.hexdigest()
            f_1.close()
            f_1_m2_server = self.client.recv(1024).decode()
            if f_1_m2 == f_1_m2_server :
                print(\n下载完成!)
                self.client.send(客户端已经成功获取完整文件!.encode())
            else:
                print(传输异常)
                self.client.send(客户端获取文件不完整或存在异常!.encode())
        else:
            print(确认信息为no,文件可能不存在或有其他问题!)

    def file_put(self,filename):
        #上传文件
        self.client.send(put.encode())  # 先发送方法
        print(self.client.recv(1024).decode())  # 服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常
        if os.path.isfile(floder_path + / + filename):
            self.client.send(filename.encode())
            print(self.client.recv(1024).decode())  #拒绝粘包
            cal = os.stat(floder_path + / + filename).st_size #获取文件大小
            self.client.send(str(cal).encode()) #发送文件大小信息
            print(self.client.recv(1024).decode())  #获取反馈
            f = open(floder_path+/+filename,rb)  #打开文件
            self.client.send(f.read())
            f.close()
            f_1 = open(floder_path + / + filename, rb)  #一致性校验
            m2 = hashlib.md5()
            m2.update(f_1.read())
            f_1_m2 = m2.hexdigest()
            f_1.close()
            f_1_m2_server = self.client.recv(1024).decode()
            if f_1_m2 == f_1_m2_server:
                print(上传完成!)
                self.client.send(客户端已经成功上传完整文件!.encode())
            else:
                print(传输异常)
                self.client.send(客户端上传文件不完整或存在异常!.encode())
                print(self.client.recv(1024).decode())
        else:
            self.client.send(no.encode())
            print(查无此文件)
    def file_open(self,filename):
        self.client.send(open.encode())  # 先发送方法
        print(self.client.recv(1024).decode())  # 服务器确认信息,后面可以加入判断,判断服务器目前状态是否正常
        self.client.send(filename.encode()) #发送目录名称
        print(self.client.recv(1024).decode())
        self.client.send(防止粘包.encode())
        confirm = self.client.recv(1024).decode()  # 服务器确认文件是否存在,如果存在返回yes,如果不存在,返回no
        if confirm != no:
            self.client.send(please give me!.encode())  #自动发送给服务器
            file_dir = self.client.recv(1024).decode()
            print(file_dir)

        else:
            print(确认信息为no,目录可能不存在或有其他问题!)


if __name__ == __main__ :
    socket_ftp = Scoket_ftp()
    option = input(‘‘‘
    ---------option----------
    1.创建用户
    2.登录
    3.退出
    ‘‘‘).strip()
    if option == 1:
        socket_ftp.client_user_register()
    elif option == 2:
        socket_ftp.client_conn(localhost,6969)

        socket_ftp.client_interaction()
    elif option == 3:
        exit()

    else:
        print(wrong!)
        exit()

 

以上是关于python 学习分享-实战篇高级的ftp的主要内容,如果未能解决你的问题,请参考以下文章

Python学习代码——高级篇

GitHub寻宝机器学习实战python3代码分享

一起来学习吧~~100例python题实战提高篇(附带答案)

Framework学习实战高级视频--SystemServer启动FallbackHome篇

分享《TensorFlow技术解析与实战》高清中文PDF+源代码

Flink从入门到精通100篇(二十二)-微博基于Flink的机器学习实战项目