zoukankan      html  css  js  c++  java
  • day38作业

    1、整理GIL解释器锁,解释以下问题
    1、什么是GIL

      Global  Interpreter  Lock 全局解释器锁
    2、有了GIL会对单进程下的多个线程造成什么样的影响

      使得单进程下的多线程按照串行的方式使用解释器资源。
    3、为什么要有GIL

      放置线程竞争解释器资源,导致使用出错,也使得解释器的内部数据被多线程修改出现错误。
    4、GIL与自定义互斥锁的区别,多个线程争抢GIL与自定义互斥锁的过程分析

      全局锁不能保证自己开启的线程安全  但是保证解释器中的数据的安全的

      GIL 在线程调用解释器时 自动加锁  在IO阻塞时或线程代码执行完毕时 自动解锁

      自定义互斥锁需要自己手动上锁,手动释放。
    5、什么时候用python的多线程,什么时候用多进程,为什么?

      多线程用于密集io操作的程序,而多进程多用于密集计算的程序当中,因为全局解释器锁对于,单一进程下的多进程使用一个cpu核心,多io操作的程序主要消耗时间为io操作,使用多线程内存消耗小,效率不下于多进程。对于密集计算型程序,使用多进程的每个cpu的核心都能被利用,效率大于单核心的处理。

    2、进程池与线程池

    1、池的用途,为何要用它

      就是一个装进程的容器

    2、池子里什么时候装进程什么时候装线程?

      密集io操作的程序使用多线程、密集计算的操作使用多进程

    3、基于进程池与线程池实现并发的套接字通信

    客户端

    import socket
    
    client = socket.socket()
    client.connect(("127.0.0.1",3555))
    while True:
        msg = input(">>>")
        client.send(msg.encode("utf-8"))
        data = client.recv(1024)
        print(data.decode("utf-8"))

    服务端(进程池和线程池)

    from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
    #导入进程池
    import socket
    
    def task(client):
        while True:
            try:
                data = client.recv(1024)
                print(data.decode("utf-8"))
                if not data:
                    client.close()
                    break
                client.send(data.upper())
            except Exception:
                print("客户端断开")
                client.close()
                break
    
    if __name__ == '__main__':
        server = socket.socket()
        server.bind(("127.0.0.1",3555))
        server.listen(5)
        #创建进程池默认个数为cpu的核心数
        # pool = ProcessPoolExecutor()
        #创建线程池默认个数为cpu核心的5倍
        pool = ThreadPoolExecutor()
        while True:
            client,addr = server.accept()
            pool.submit(task,client)

    4、基于线程池实现一个可以支持并发通信的套接字,完成以下功能?

    执行客户端程序,用户可选的功能有:
    1、登录
    2、注册
    3、上传
    4、下载

    思路解析:
    1、执行登录,输入用户名egon,密码123,对用户名egon和密码进行hash校验,并加盐处理,将密文密码发送到服务端,与服务端事先存好用户名与密文密码进行对比,对比成功后,
    在服务端内存中用hash算法生成一个随机字符串比如eadc05b6c5dda1f8772c4f4ca64db110
    然后将该字符串发送给用户以及登录成功的提示信息发送给客户端,然后在服务存放好
    current_users={
    'a3sc05b6c5dda1f8313c4f4ca64db110':{'uid':0,'username':'alex'},
    'e31adfc05b6c5dda1f8772c4f4ca64b0':{'uid':1,'username':'lxx'},
    'eadc05b6c5dda1f8772c4f4ca64db110':{'uid':2,'username':'egon'},

    }

    用户在收到服务端发来的'eadc05b6c5dda1f8772c4f4ca64db110'以及登录成功的提示信息后,以后的任何操作都会携带该随机字符串'eadc05b6c5dda1f8772c4f4ca64db110‘,服务端会根据该字符串获取用户信息来进行与该用户匹配的操作

    在用户关闭连接后,服务端会从current_users字典中清除用户信息,下次重新登录,会产生新的随机字符串
    这样做的好处:
    1、用户的敏感信息全都存放到服务端,更加安全
    2、每次登录都拿到一个新的随机的字符串,不容易被伪造

    2、执行注册功能,提交到服务端,然后存放到文件中,如果用户已经存在则提示用户已经注册过,要求重新输入用户信息

    3、执行上次下载功能时会携带用户的随机字符串到服务端,如果服务端发现该字符串not in current_users,则要求用户先登录

     客户端

    import socket,struct,json,hashlib,os
    
    client = socket.socket()
    client.connect(("127.0.0.1",4566))
    current_code = None
    
    def send_data_to_server(data):
        """
    
        :param client: 连接
        :param data: 符合json格式的数据
        :return:
        """
        json_data = json.dumps(data)
        # 在转化可传输的二进制形式
        bytes_data = json_data.encode("utf-8")
        # 计算传输需要的的长度
        len_bytes = len(bytes_data)
        # 将长度整形打包成为二进制位
        b_len = struct.pack("i", len_bytes)
        # 传输数据
        client.send(b_len)
        client.send(bytes_data)
    
    def get_recv_data():
        """
        接受服务返回的数据
        :param client:
        :return:
        """
        b_len = client.recv(4)
        # 转换为数字
        bytes_len = struct.unpack("i", b_len)[0]
        recv_data = b""
        len_recv = 0
        while len_recv < bytes_len:
            r_data = client.recv(1024)
            recv_data += r_data
            len_recv += len(r_data)
        str_data = recv_data.decode("utf-8")
        data = json.loads(str_data)
        return data
    
    def encryption(pwd):
        res = hashlib.md5(pwd.encode("utf-8"))
        return res.hexdigest()
    
    def regist():
        """
        注册
        :return:
        """
        while True:
            name = input("请输入你的姓名(q 退出)").strip()
            if name == "q":
                return
            pwd = input("请输入你的密码").strip()
            if name and pwd:
                func_id = 1
                pwd = encryption(pwd)
                dic = {"name":name,"pwd":pwd,"func_id":func_id}
                send_data_to_server(dic)
                #等待接收服务端的返回
                msg_dic = get_recv_data()
                print(msg_dic["msg"])
                if msg_dic["flag"]:
                    return
            else:
                print("用户和密码不能为空")
    
    def login():
        """
        登录,获得连接特征码
        :return:
        """
        while True:
            name = input("请输入你的姓名(q 退出)").strip()
            if name == "q":
                return
            pwd = input("请输入你的密码").strip()
            if name and pwd:
                func_id = 1
                pwd = encryption(pwd)
                dic = {"name": name, "pwd": pwd, "func_id": func_id}
                send_data_to_server(dic)
                msg_dic =get_recv_data()
                print(msg_dic["msg"])
                if msg_dic["flag"]:
                    global current_code
                    current_code = msg_dic["current_code"]
                    return 
            else:
                print("用户名和密码不能为空")
    #上传
    def upload():
        while True:
            filename = input("请输入文件路径(q 退出)").strip()
            if filename == 'q':
                return 
            if not filename:
                print("文件名不能为空")
                continue
            if os.path.exists(filename):
                file_name = os.path.split(filename)[1]
                file_size = os.path.getsize(filename)
                file_dic = {"file_name":file_name,"file_size":file_size,"current_code":current_code}
                send_data_to_server(file_dic)
                with open(filename,"rb") as f:
                    for line in f:
                        client.send(line)
                        
                msg_dic = get_recv_data()
                print(msg_dic["msg"])
                if msg_dic["flag"]:
                    return 
            else:
                print("文件路劲不存在")
                continue
    
    
    #下载
    def download():
        while True:
            filename = input("请输入下文件的名字(q 退出)").strip()
            if filename == "q":
                return 
            if not filename:
                print("文件不能为空")
                continue
            dic = {"filename":filename}
            send_data_to_server(dic)
            file_dic = get_recv_data()
            print(file_dic["msg"])
            if file_dic["flag"]:
                filename = file_dic["filename"]
                filesize = file_dic["file_size"]
                file_path = os.path.join(r"F:Python_exeday38userdb",filename)
                b_len = 0
                with open(file_path,"ab") as f:
                    while b_len<filesize:
                        data = client.recv(1024)
                        f.write(data)
                        b_len += len(data)
                return 
            
            
    
    func = {"1":regist,"2":login,"3":upload,"4":download}
    while True:
        print("""
        1、注册
        2、登录
        3、上传
        4、下载
        q 退出
        """)
        index = input("请输入你想要的操作").strip()
        if index == "q":
            break
        if index in func:
            func[index]()
        else:
            print("错误操作")

     服务端

    from concurrent.futures import ThreadPoolExecutor
    import socket,struct,json
    import hashlib
    import time
    import os
    
    server  = socket.socket()
    server.bind(("127.0.0.1",4566))
    server.listen(5)
    current_user = {}
    
    def get_recv_data(client):
        """
        接受服务返回的数据
        :param client:
        :return:
        """
        b_len = client.recv(4)
        # 转换为数字
        bytes_len = struct.unpack("i", b_len)[0]
        recv_data = b""
        len_recv = 0
        while len_recv < bytes_len:
            r_data = client.recv(1024)
            recv_data += r_data
            len_recv += len(r_data)
        str_data = recv_data.decode("utf-8")
        data = json.loads(str_data)
        return data
    
    #发送个客户端
    def send_data_to_client(client,data):
        """
    
        :param client: 连接
        :param data: 符合json格式的数据
        :return:
        """
        json_data = json.dumps(data)
        # 在转化可传输的二进制形式
        bytes_data = json_data.encode("utf-8")
        # 计算传输需要的的长度
        len_bytes = len(bytes_data)
        # 将长度整形打包成为二进制位
        b_len = struct.pack("i", len_bytes)
        # 传输数据
        client.send(b_len)
        client.send(bytes_data)
    
    #用户是否存在
    def get_user(name):
        with open(r"F:Python_exeday38user_db.json","r",encoding="utf-8") as f:
            users = json.load(f)
        for user in users:
            if user["name"] == name:
                return user
    
    #添加用户到文件中去
    def save_user_to_file(name,pwd):
        dic = {"name":name,"pwd":pwd}
        with open(r"F:Python_exeday38user_db.json","r",encoding="utf-8") as f:
            users = json.load(f)
        users.append(dic)
        with open(r"F:Python_exeday38user_db.json", "w", encoding="utf-8") as f:
            json.dump(users,f)
    
    
    def regist(client,data):
        name = data["name"]
        pwd = data["pwd"]
        #校验用户是否存在
        user = get_user(name)
        if user:
            msg = "用户已存在"
            flag = False
        else:
            save_user_to_file(name,pwd)
            msg = "创建用户成功"
            flag = True
        msg_dic = {"msg":msg,"flag":flag}
        send_data_to_client(client,msg_dic)#发送给客户端
    
    def login(client,data):
        name = data["name"]
        pwd = data["pwd"]
        # 校验用户是否存在
        user = get_user(name)
        if user:
            if pwd == user["pwd"]:
                msg = "登录成功"
                flag = True
                #生成一个current_code加入current_user,并返回一个current_code给客户端
                code = "%s%s%s"%(name,pwd,time.time())
                current_code = hashlib.md5(code.encode("utf-8")).hexdigest()
                current_user[current_code] = {"username":name}
                msg_dic = {"msg":msg,"flag":flag,"current_code":current_code}
            else:
                msg = "密码错误"
                flag = False
                msg_dic = {"msg": msg, "flag": flag}
        else:
            msg = "用户不存在,请先注册"
            flag = False
            msg_dic = {"msg": msg, "flag": flag}
    
        send_data_to_client(client,msg_dic)
    
    def upload(client,data):
        if data["current_code"] in current_user:
            file_name = data["file_name"]
            file_size = data["file_size"]
            by_len = 0
            with open(r'F:Python_exeday38server_db\%s'%file_name,"ab") as f:
                while by_len<file_size:
                    data = client.recv(1024)
                    f.write(data)
                    by_len += len(data)
            msg = "上传成功"
            flag = True
        else:
            msg = "用户认证失败"
            flag = False
        msg_dic = {"msg":msg,"flag":flag}
        send_data_to_client(client,msg_dic)
    
    
    def download(client,data):
        filename = data["filename"]
        file_path = os.path.join("F:Python_exeday38server_db",filename)
        if not os.path.exists(file_path):
            msg = "文件不存在"
            flag = False
            file_dic = {"msg":msg,"flag":flag}
            send_data_to_client(client, file_dic)
        else:
            msg = "文件存在"
            flag = True
            file_size = os.path.getsize(file_path)
            file_dic = {"msg":msg,"flag":flag,"filename":filename,"file_size":file_size}
            send_data_to_client(client,file_dic)
            with open(file_path,"rb") as f:
                for line in f:
                    client.send(line)
    
    
    
    #总成函数
    def task(client):
        while True:
            try:
                data = get_recv_data(client)
                print(data)
                if not data:
                    client.close()
                    return
                #功能列表
                funs = {"1":regist,"2":login,"3":upload}
                print(1)
                func_id = data["func_id"]
                print(2)
                funs[str(func_id)](client,data)
                print(3)
            except Exception:
                print("客户端断开连接")
                client.close()
                break
    
    
    
    
    
    pool = ThreadPoolExecutor()
    while True:
        client,addr = server.accept()
        pool.submit(task,client)
  • 相关阅读:
    EasyUI dialog
    winform 收集
    ASP.NET文件下载,直接向客户端输出文件(转)
    反射收集
    Sql Server 2008 R2 备份数据库报错
    慎用Ext.QuickTip和Ext.QuickTips(转)
    使用正则Regex来移除网页的ViewState(转)
    mysql 实现远程链接(转)
    MySqlBackup.NET,C# mysql备份数据库
    Firefox下站长统计代码不起作用
  • 原文地址:https://www.cnblogs.com/msj513/p/9949261.html
Copyright © 2011-2022 走看看