zoukankan      html  css  js  c++  java
  • 项目

    文件说明

    #程序目录及文件说明
    
    #####################################
    #   db             数据保存文件夹	  #
    #      client      客户端保存文件	  #
    #      server      服务器保存文件	  #
    #      user_info   用户保存文件      #
    #####################################
    
    server.py   服务器运行主文件
    app.py      服务器接口文件
    
    client.py   客户端文件
    api.py      客户端接口文件
    
    多线程连接,支持并发
    

    server.py

    import socket, app, json, struct
    from threading import Thread
    
    server = socket.socket()
    server.bind(('127.0.0.1', 1688))
    server.listen(5)
    
    urls = {
        'login': app.login,
        'register': app.register,
        'upfile': app.upfile,
        'get_file_names': app.get_file_names,
        'download': app.download
    }
    
    
    def connlient(c, addr):
        while True:
            try:
                req = app.recv_data(c)
                # 拿出func判断是否正确的 如果是则调用相应的函数
    
                func_name = req["func"]
                if func_name in urls:
    
                    # 判断该请求是否是一个上传文件的请求
                    if func_name == "upfile":
                        temp_path = app.recv_file(c, req)
                        # 将路径加入到请求数据中 交给应用层来处理
                        req["temp_path"] = temp_path
    
                    resp = urls[func_name](req)  # 调用业务逻辑函数 拿到处理后的结果
                    # 这个地方判断返回的数据如果是一个文件路径 那就打开文件发给客户端
                    if "file" in resp:
                        print('到这了!!!!')
                        file = resp.pop("file")  # 从响应中取出文件对象
    
                        app.send_resp(c, resp)  # 发送文件信息给客户端
                        app.send_file(file, c)  # 发送文件数据
    
                    else:  # 表示普通请求
                        app.send_resp(c, resp)  # 发送文件信息给客户端
    
                else:
    
                    """要调用的函数不存在!"""
                    pass
    
            except Exception as e:
    			
                print(f'{addr}断开连接!{e}') # 客户端异常断开连接,直接断开!
                break
    
    
    print('start...')
    while True:
        c, addr = server.accept()
        t = Thread(target=connlient, args=(c, addr)) #有客户端连接,开启线程
        t.start()
    
    

    app.py

    import json, os, struct
    
    
    # 接收数据
    def recv_data(client):
        head_len = client.recv(4)
        if not head_len:
            client.close()
            return
    
        json_len = struct.unpack('i', head_len)[0]
    
        # 收真是数据
        json_data = client.recv(json_len)
        if not json_data:
            client.close()
            return
        json_data = json.loads(json_data.decode("utf-8"))
        # print(json_data)
        return json_data
    
    
    # 发送响应数据
    def send_resp(client, resp):
        # 发送请求
        data_json = json.dumps(resp).encode('utf8')
        # 发送长度
        client.send(struct.pack('i', len(data_json)))
    
        # 发送数据
        client.send(data_json)
    
    
    def send_filel_list(client, resp):
        # 发送请求
        data_json = json.dumps(resp).encode('utf8')
        # 发送长度
        client.send(struct.pack('i', len(data_json)))
    
        # 发送数据
        client.send(data_json)
    
    
    # 接受文件数据,存入硬盘,返回路径
    def recv_file(client, request):
        total_size = request['size']
        recv_size = 0
    
        path = os.path.join('db', 'server', request['name'])
        with open(path, 'wb') as f:
            while recv_size < total_size:
                if total_size - recv_size >= 1024:
                    data = client.recv(1024)
                else:
                    data = client.recv(total_size - recv_size)
                f.write(data)
                recv_size += len(data)
    
        path = os.path.abspath(request['name'])
        return path
    
    #登录接口
    def login(requester):
        res = os.path.exists(f"db\user_info\{requester['uname']}.json")
        if res:
            with open(f"db\user_info\{requester['uname']}.json", 'r', encoding='utf8') as fr:
                data = json.load(fr)
                if data['pwd'] == requester['pwd']:
                    return {'msg': '登录成功', 'flag': True}
                return {'msg': '登录失败,用户名或密码错误', 'flag': False}
    
        else:
            return {'msg': '登录失败,用户名不存在', 'flag': False}
    
    #注册接口
    def register(request):
        res = os.path.exists(f"db\user_info\{request['uname']}.json")
        print(res)
        if res:
            return {'msg': '注册失败,用户名存在', 'flag': False}
        else:
            with open(f"db\user_info\{request['uname']}.json", 'w', encoding='utf8') as fw:
                user_info = {'username': request['uname'], 'pwd': request['pwd']}
                json.dump(user_info, fw)
                fw.flush()
            return {'msg': '注册成功', 'flag': True}
    
    
    def upfile(requester):
        print(requester)
        return {'msg': '上传成功', 'flag': True}
    
    
    def get_file_names(requests):
        """返回所有文件列表"""
        names = os.listdir("db\server")
        resp = {"names": names}
        return resp
    
    
    def download(requests):
        """
        1.接收到请求信息
        2.获取文件的大小返回给客户端
        3.返回的信息中不止包含大小 还包含一个file 是一个文件
        :return:
        """
        path = os.path.join("db", 'server', requests["name"])
        resp = {"size": os.path.getsize(path), "file": open(path, "rb")}
    
        return resp
    
    
    def send_file(file, c):
        while True:
            data = file.read(1024)
            if not data:
                break
            c.send(data)
    
    

    client.py

    import api
    
    
    def run():
        funcs = {"1": api.login, "2": api.register, "3": api.upload, "4": api.download}
    
        while True:
            print("""
            ------------
            |  1.登录   |
            |  2.注册   |
            |  3.上传   |
            |  4.下载   |
            |  6.退出   |
            ------------
            """)
            f = input("Please choose the function you want:")
            if f == "6":
                print("再见了 勇士!")
                break
            if f in funcs:
                funcs[f]()
            else:
                print("输入不正确! 请重试!")
    
    
    if __name__ == '__main__':
        run()
    
    

    api.py

    import os, struct, json, socket
    
    client = socket.socket()
    client.connect(('127.0.0.1', 1688))
    username = {'uname': None}
    
    
    def send_request(data):
        # 发送请求
        data_json = json.dumps(data).encode("utf-8")
        # 送长度
        client.send(struct.pack("i", len(data_json)))
    
        # 发送数据
        client.send(data_json)
    
        # 接收响应数据
        # 收长度
        l = struct.unpack("i", client.recv(4))[0]
        # 收数据
        response = json.loads(client.recv(l).decode("utf-8"))
    
        return response
    
    #给服务器发送数据,上传
    def send_file(path, data):
        data_json = json.dumps(data).encode('utf8')
    
        client.send(struct.pack('i', len(data_json)))
    
        client.send(data_json)
    
        with open(path, 'rb') as f:
            while True:
                data = f.read(1024 * 1)
                if not data:
                    break
                client.send(data)
    
        l = struct.unpack('i', client.recv(4))[0]
        response = json.loads(client.recv(l).decode('utf8'))
        return response
    
    #登录装饰器
    def deco(func):
        def wrapper(*args, **kwargs):
            if not username['uname']:
                if login():
                    res = func(*args, **kwargs)
                    return res
                else:
                    print('登录失败')
            else:
                res = func(*args, **kwargs)
                return res
    
        return wrapper
    
    #登录接口
    def login():
        uname = input('uname:').strip()
        pwd = input('pwd:').strip()
    
        if uname and pwd:
            data = {'uname': uname, 'pwd': pwd, 'func': 'login'}
            resp = send_request(data)
            print(resp)
            msg = resp['msg']
            flag = resp['flag']
            global username  # 全局变量声明
            username = {'uname': uname}  # 登录成功后记录登录名
            print(msg)
            if flag:
                return True
            else:
                return False
    
    #注册接口
    def register():
        uname = input('uname:')
        pwd = input('pwd:')
    
        if uname and pwd:
            data = {'uname': uname, 'pwd': pwd, 'func': 'register'}
            resp = send_request(data)
            print(resp)
    
    
    @deco
    def upload():
        path = input('请输入文件路径:').strip()
        if not os.path.exists(path) or not os.path.isfile(path):
            print('文件路径错误!必须是一个正确的文件路径')
            return
    
        name = os.path.basename(path)
        size = os.path.getsize(path)
    
        file_info = {'name': name, 'size': size, 'func': 'upfile'}
    
        resp = send_file(path, file_info)
        print(resp)
    
    
    def choose_name():
        req = {"func": "get_file_names"}
        resp = send_request(req)
        # 返回的数据结构 {"names":["张三","李四"]}
        print('/*/*/*/*', resp)
        if not resp["names"]:
            print("暂时没有文件!")
            return
        # 遍历输出
        for k, v in enumerate(resp["names"]):
            print(k, v)
        n = input("请输入序号:").strip()
        if n.isdigit():
            n = int(n)
            if n >= 0 and n < len(resp["names"]):
                filename = resp["names"][n]
                return filename
    
    @deco
    def download():
        """
        1.先获取服务器文件列表
        2.选择一个正确文件名称
        3.把文件名称信息发送给服务器
        4.服务器读取文件数据  发送给客户端
        5.客户端接收文件数据
        :return:
        """
        name = choose_name()
        if not name:
            print("没有选择一个正确的文件名称!")
            return
        req = {"name": name, "func": "download"}
        file_info = send_request(req)
    
        # file_info = {"size":1010110}
        total_szie = file_info["size"]
        recv_size = 0
        path = os.path.join("db", 'client', name)
        f = open(path, "wb")
        while recv_size < total_szie:
            if total_szie - recv_size < 1024:
                data = client.recv(total_szie - recv_size)
            else:
                data = client.recv(1024)
            f.write(data)
            recv_size += len(data)
        f.close()
        print("下载成功!")
    
    
  • 相关阅读:
    linux Crontab 使用
    彻底搞懂 call() 和 apply() 方法
    (day10) 28. 实现strStr()
    (day9)357. 计算各个位数不同的数字个数
    (day7) 168. Excel表列名称
    (day6) 319. 灯泡开关
    (day5)350 两个数组的交集 II
    (day4)581.最短无序连续子数组
    day3 字符串的排列
    JS类型转换
  • 原文地址:https://www.cnblogs.com/bladecheng/p/11151840.html
Copyright © 2011-2022 走看看