• FTP


    环境:windows Python  3.5
    实现功能:
    注册/登陆,不同用户家目录不同,查看登陆用户家目录下文件,上传到登陆用户家目录下,从登陆用户家目录下下载
    结构:
    FTP--|
    clients--|
    conf--|
    config.py-- ……客户端参数,IP,PORT
    core--|
    client.py-- ……客户端启动文件
    servers--|
    conf--|
    config.py-- ……服务端参数,IP,PORT,上传最大文件大小,家目录路径
    core--|
    client.py-- ……服务端启动文件
    db --|
    data.py-- ……存储,读取用户信息
    home--| 存放不同用户家目录

    如何使用:
    启动服务端servers.core.servers.py文件
    启动客户端clients.core.client.py文件(可多用户登陆)
    未注册先注册,注册后登陆
    根据需求选择相应操作:
    上传默认路径为登陆用户家目录 home/name
    下载默认从登陆用户家目录下下载文件,使用下载前先上传文件,否则将无任何文件可下载

    客户端代码:

    import os
    import configparser
    PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    class Configuration(object):
        def __init__(self):
            self.config = configparser.ConfigParser()
            self.name = PATH+os.sep+"conf"+os.sep+"system.ini"
    
        def init_config(self):
            # 初始化配置文件,ip :客户端IP,port:客户端端口
            if not os.path.exists(self.name):
                self.config["config"] = {"ip":"localhost","port":6666}
                self.config.write(open(self.name, "w", encoding="utf-8", ))
    
        def get_config(self, head="config"):
            '''
            获取配置文件数据
            :param head: 配置文件的section,默认取初始化文件config的数据
            :return:返回head中的所有数据(列表)
            '''
            self.init_config() # 取文件数据之前生成配置文件
            self.config.read(self.name, encoding="utf-8")
            if self.config.has_section(head):
                section=self.config.sections()
                return self.config.items(section[0])
    config.py
    #!/usr/bin/env python
    # -*-coding:utf-8-*-
    # _author_=zh
    import os
    import sys
    import socket
    import hmac
    PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(PATH)
    from conf import config
    
    
    class Client(object):
    
        def __init__(self, ip, port):
            # 创建连接
            self.ip = str(ip)
            self.port = int(port)
            self.client = socket.socket()
            self.client.connect((self.ip, self.port))
    
        def send_pwd(self):
            # 注册和登录中公有的操作,返回服务器返回的标识,0为成功,1为失败,返回登录人名称
            logo_name = input("name:")
            pwd = input("pwd:")
            data = "%s" % ([logo_name, self.encrypt("pwd", pwd)])
            self.client.sendall(data.encode())
            accept_data = self.client.recv(1024)
            return accept_data, logo_name
    
        def login(self):
            # 注册
            self.client.sendall("login".encode())
            while True:
                accept_data, logo_name = self.send_pwd()
                if accept_data.decode() == "0":
                    return None
                elif accept_data.decode() == "1":
                    print("账号已存在")
                    break
    
        def logon(self):
            # 登录,登录成功返回登录人姓名
            self.client.sendall("logon".encode())
            count = 0
            while True:
                accept_data, logo_name = self.send_pwd()
                if accept_data.decode() == "0":
                    return logo_name
                elif accept_data.decode() == "1":
                    print("账号或密码错误")
                    count += 1
                    if count > 2:
                        break
    
        def watch(self, logo_name):
            # 查看登陆用户家目录下文件
            self.client.sendall("watch".encode())
            data = ["dir", logo_name]
            self.client.sendall(str(data).encode())
            accept_data = self.client.recv(1024)
            accept_data = accept_data.decode()
            print(accept_data)
    
        def upload(self, logo_name):
            # 上传,上传到home目录下
            self.client.send("upload".encode())
            path = input("请输入需要上传的文件路径:")
            length = os.path.getsize(path)
            file_name = path[path.rfind("\")+1:]
            data = ("['%s','%s','%s']" % (length, file_name, logo_name)).encode()
            self.client.send(data)
            sign = (self.client.recv(1024)).decode()
            if sign == "1":
                print("家目录空间不足")
            else:
                get_length = (self.client.recv(1024)).decode()
                if get_length == "None":
                    print("文件已存在")
                else:
                    get_length = int(get_length)
                    conf = hmac.new("file".encode())
                    with open(path, "rb") as send_data:
                        send_data.seek(get_length)
                        send_data = send_data.read()
                        conf.update(send_data)
                        pwd = conf.hexdigest()
                    self.client.sendall(send_data)
                    if (self.client.recv(1024)).decode() == "0":
                        self.client.send(pwd.encode())
                    if (self.client.recv(1024)).decode() == "0":
                        print("上传成功")
                    else:
                        print("上传失败")
    
        def download(self, logo_name):
            # 下载,从登陆用户家目录下载到指定位置
            self.client.send("download".encode())
            self.client.send(("%s" % logo_name).encode())
            show_data = self.client.recv(1024)
            print(show_data.decode())
            while True:
                file_name = input("请输入需要下载的文件名:")
                if "." not in file_name:
                    print("文件名需带格式后缀")
                address = input("请输入下载路径:")
                if os.path.exists(address):
                    break
                print("文件路径不存在,重新输入")
            self.client.send(file_name.encode())
            length_data = self.client.recv(1024)
            length_data = eval(length_data.decode())
            if length_data == 1:
                print("文件不存在")
            else:
                length = length_data[0]
                pwd = length_data[1]
                self.client.send("0".encode())
                all_data = b''
                while True:
                    if len(all_data) == int(length):
                        break
                    else:
                        data = self.client.recv(1024)
                        all_data += data
                        ret = len(all_data) / int(length)
                        num = int(ret * 100)
                        view = '
     [%-100s]%d%%' % ("=" * num, 100,)
                        sys.stdout.write(view)
                        sys.stdout.flush()
                path = address+os.sep+file_name
                if os.path.isfile(path):
                    print("文件已存在")
                else:
                    conf = hmac.new("file".encode())
                    with open(path, "wb") as file:
                        file.write(all_data)
                        conf.update(all_data)
                        new_pwd = conf.hexdigest()
                    if new_pwd == pwd:
                        print("下载成功")
                    else:
                        print("下载失败")
                        os.remove(path)
    
        def encrypt(self, keys, data):
            #  hmac加密
            conf = hmac.new(keys.encode())
            conf.update(data.encode())
            return conf.hexdigest()
    
    
    if __name__ == '__main__':
        while True:
            info = config.Configuration()
            info_list = info.get_config()
            obj_client = Client(info_list[0][1], info_list[1][1])
            info = '''---welcome---
            1.登录
            2.注册
            '''
            print(info)
            num = input("-->")
            setattr(obj_client, "1", obj_client.logon)
            setattr(obj_client, "2", obj_client.login)
            if hasattr(obj_client, num):
                name = getattr(obj_client, num)()
            else:
                print("输入错误,请重新输入")
                continue
            if name:
                break
            else:
                print("请登录")
        while True:
            info = '''
        1.查看家目录下文件
        2.上传
        3.下载
        4.注销
        '''
            print(info)
            num = input("-->")
            if num == "4":
                exit()
            setattr(obj_client, "1", obj_client.watch)
            setattr(obj_client, "2", obj_client.upload)
            setattr(obj_client, "3", obj_client.download)
            if hasattr(obj_client, num):
                getattr(obj_client, num)(name)
            else:
                print("输入错误,请重新输入")
                continue
    client

    服务端代码:

    import os
    import configparser
    PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    
    class Configuration(object):
        def __init__(self):
            self.config = configparser.ConfigParser()
            self.name = PATH+os.sep+"conf"+os.sep+"system.ini"
    
        def init_config(self):
            # 初始化配置文件,IP:服务端IP,port:服务端端口,limit_size:家目录容量,HOME_PATH:用户家目录地址
            if not os.path.exists(self.name):
                self.config["config"] = {"ip": "localhost", "port": 6666, "limit_size": 10240000,
                                         "HOME_PATH": PATH+os.sep+"home"+os.sep}
                self.config.write(open(self.name, "w", encoding="utf-8", ))
    
        def get_config(self, head="config"):
            '''
            获取配置文件数据
            :param head: 配置文件的section,默认取初始化文件config的数据
            :return:返回head中的所有数据(列表)
            '''
            self.init_config()  # 取文件数据之前生成配置文件
            self.config.read(self.name, encoding="utf-8")
            if self.config.has_section(head):
                section = self.config.sections()
                return self.config.items(section[0])
    config.py
    import shelve
    import os
    PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))+os.sep+"db"+os.sep
    
    
    def write(name, data):
        '''
        存储个人信息
        :param data: 存储的数据
        :param name: shelve的key
        '''
        file = shelve.open("%sdata" % PATH)
        file[name] = data
        file.close()
    
    
    def read(name):
        '''
        读取个人信息
        :param name:存储时传入的name
        :return:返回个人信息
        '''
        file = shelve.open("%sdata" % PATH)
        if name in list(file.keys()):
            data = file[name]
        else:
            data = None
        file.close()
        return data
    data.py
    #!/usr/bin/env python
    # _*_coding:utf-8_*_
    # _author_=zh
    import os
    import locale
    import codecs
    import subprocess
    PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))+os.sep+"home"
    
    
    def order(cmd):
        '''
        执行命令结果输出到屏幕
        :param cmd: 输入的命令
        :return:
        '''
        word = subprocess.Popen(args=cmd, cwd=PATH, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        # 将结果decode输出,自动获取不同操作系统的默认编码
        return word.stderr.read().decode(codecs.lookup(locale.getpreferredencoding()).name), 
            word.stdout.read().decode(codecs.lookup(locale.getpreferredencoding()).name) 
    cmd.py
    import os
    import sys
    import socketserver
    import cmd
    import hmac
    
    PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(PATH)
    import db
    from conf import config
    
    
    class Myserver(socketserver.BaseRequestHandler):
    
        def handle(self):
            self.conn = self.request
            self.addr = self.client_address
            print("一个连接已进入")
            try:
                while True:
                    # 客户端传入对应的方法名称,调用服务端相同的方法名
                    accept_data = self.conn.recv(1024)
                    accept_data = accept_data.decode("utf-8")
                    if accept_data in list(Myserver.__dict__.keys()):
                        func = 'self.%s' % accept_data
                        eval(func)()
                    else:
                        print("服务端%s方法缺失" % accept_data)
                        break
            except (ConnectionResetError, ConnectionAbortedError, SyntaxError):
                print("连接关闭")
            self.conn.close()
    
        def logon(self):
            # 登录,登录成功自动创建家目录,目录名为登录名
            while True:
                accept_data = self.conn.recv(1024)
                accept_data = eval(accept_data.decode("utf-8"))
                list_data = db.data.read(accept_data[0])
                if not list_data:
                    self.conn.send("1".encode())
                else:
                    if accept_data == list_data:
                        cmd.order("mkdir %s" % accept_data[0])
                        self.conn.send("0".encode())
                        break
    
        def login(self):
            # 注册
            accept_data = self.conn.recv(1024)
            accept_data = eval(accept_data.decode("utf-8"))
            list_data = db.data.read(accept_data[0])
            if list_data:
                self.conn.send("1".encode())
            else:
                db.data.write(accept_data[0], accept_data)
                self.conn.send("0".encode())
    
        def watch(self):
            # 查看登陆用户家目录下文件信息并返回给客户端
            accept_data = self.conn.recv(1024)
            accept_data = eval(accept_data.decode("utf-8"))
            send_data = "%s %s%s" % (accept_data[0], info_list[3][1], accept_data[1])
            eer, out = cmd.order(send_data)
            self.conn.send(("%s,%s" % (eer, out)).encode())
    
        def upload(self):
            # 上传到登陆用户的家目录
            accept_data = self.conn.recv(1024)
            accept_data = accept_data.decode("utf-8")
            accept_data = eval(accept_data)
            # accept_data = [length, file_name, logo_name]
            if int(info_list[2][1]) < int(accept_data[0]):
                self.conn.send("1".encode())
            else:
                self.conn.send("0".encode())
                path = info_list[3][1]+accept_data[2]+os.sep+accept_data[1]
                accept_data[0] = int(accept_data[0])
                try:
                    length = os.path.getsize(path)
                except FileNotFoundError:
                    length = 0
                if accept_data[0] == length:
                    self.conn.send("None".encode())
                else:
                    accept_data[0] = accept_data[0]-length
                    self.conn.sendall(("%s" % length).encode())
                    get_bytes = b''
                    while True:
                        get_data = self.conn.recv(1024)
                        if len(get_data) == accept_data[0]:
                            get_bytes = get_data
                            break
                        else:
                            get_bytes += get_data
                            if len(get_bytes) == accept_data[0]:
                                self.conn.send("0".encode())
                                break
                    if length == 0:
                        with open(path, "wb") as file:
                            file.write(get_bytes)
                    else:
                        with open(path, "ab") as file:
                            file.write(get_bytes)
                    conf = hmac.new("file".encode())
                    with open(path, "rb") as file:
                        data = file.read()
                        conf.update(data)
                        pwd = conf.hexdigest()
                    get_pwd = (self.conn.recv(1024)).decode()
                    if pwd == get_pwd:
                        self.conn.send("0".encode())
                    else:
                        self.conn.send("1".encode())
                        os.remove(path)
    
        def download(self):
            # 从登陆用户家目录下载文件,到指定目录
            logo_name = (self.conn.recv(1024)).decode()
            file_path = info_list[3][1]+os.sep+logo_name
            send_data = "dir %s" % file_path
            eer, out = cmd.order(send_data)
            self.conn.send(("%s,%s" % (eer, out)).encode())
            file_name = (self.conn.recv(1024)).decode()
            conf = hmac.new("file".encode())
            if os.path.isfile(file_path+os.sep+file_name):
                with open(file_path+os.sep+file_name, "rb") as send_data:
                    send_data = send_data.read()
                    conf.update(send_data)
                    pwd = conf.hexdigest()
                self.conn.send(("['%s','%s']" % (len(send_data), pwd)).encode())
                sign = (self.conn.recv(1024)).decode()
                if sign == "0":
                    self.conn.sendall(send_data)
            else:
                self.conn.send("1".encode())
    
    
    if __name__ == '__main__':
        info = config.Configuration()
        info_list = info.get_config()
        server = socketserver.ThreadingTCPServer((info_list[0][1], int(info_list[1][1])), Myserver)
        server.serve_forever() 
    servers.py
  • 相关阅读:
    LinuxMySQL主从复制原理图
    flask中间件请求流程
    flask02
    flask01
    笔记本电脑播放声音前后会有吱吱声
    筛法欧拉函数
    矩阵快速幂
    最短路 P1144 最短路计数【Dijkstra堆优化/SPFA】
    SPFA算法以及负环判断【模板】
    最短路 P1629 邮递员送信 【反向图求最短路】
  • 原文地址:https://www.cnblogs.com/zh-20170913/p/8028691.html
Copyright © 2020-2023  润新知