zoukankan      html  css  js  c++  java
  • Python 使用模块模拟并发处理

    socketserver模块

    我们可以通过socketserver模块来模拟并发的一个状态

    接下来我们通过使用socketserver来编写程序模拟并发的一个过程

    程序编写:

    思路:

    1. 用户注册登录界面
    2. 选择功能
      • 功能的选择
        • 上传
        • 下载
        • 查看文件
        • 删除文件
    3. 对TCP协议粘包的处理

    了解粘包:

    • 粘包就是当数据过大或者过小,导致一直存储在内存中。过小导致多次数据同时发送,过大导致数据无法接收完全。

    粘包代码:

    服务器
    import socket
    #生成一个socket对象
    soc=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    #绑定地址跟端口号
    soc.bind(('127.0.0.1',8001))
    #监听(半连接池的大小),不是连接数
    soc.listen(3)
    #等着客户端来连接,conn相当于连接通道,addr是客户端的地址
    while True:
        print('等待客户端连接')
        conn,addr=soc.accept()    #卡主,如果没有客户端连接,会一直卡在这,当有连接,才继续往下走
        print('有个客户端连接上了',addr)
        while True:
            try:
                data=conn.recv(1024)
                print(data)
                data2=conn.recv(1024)
                print(data2)
                data3=conn.recv(1024)
                print(data3)
            except Exception:
    
                break
        # 关闭通道
        conn.close()
    
    
    # 关闭套接字
    soc.close()
    
    客服端
    import socket
    
    soc=socket.socket()
    
    soc.connect(('127.0.0.1',8001))
    while True:
        in_s=input('请输入要发送的数据:')
        soc.send(b'a')
        soc.send(b'b')
        soc.send(b'c')
    
    

    通过模块实现并发

    登录界面代码实现:
    import os
    import json
    import time
    import nbK
    def register():
        user_dict = {
            'username':None,
            'password':None
        }
        while True:
            print('--------注册---------')
            name = input('请输入你的用户名').strip()
            pwd = input('请输入你要使用的密码:').strip()
            re_pwd = input('确认要使用的密码:').strip()
            if name == 'q' or name == 'Q':
                break
            if os.path.isdir(f'user/{name}'):
                print('用户已经存在')
                continue
            if pwd == re_pwd:
                print('注册成功')
                os.mkdir(f'user/{name}')
                user_dict['username'] = name
                user_dict['password'] = pwd
                with open(f'user_info/{name}.json','w') as fw:
                    json.dump(user_dict,fw)
                    fw.flush()
                break
    def login():
        s = 3
        while True:
            print('--------登录---------')
            name = input('请输入你的用户名')
            pwd = input('请输入你的密码')
            if not os.path.exists(f'user_info/{name}.json'):
                while s>0:
                    print(f'
    用户不存在,{s-1}s后跳转到注册界面',end='')
                    time.sleep(1)
                    s-=1
                print('
    ')
                register()
                continue
            with open(f'user_info/{name}.json','r') as fr:
                user_dic = json.load(fr)
            if name == user_dic.get('username') and pwd == user_dic.get('password'):
                print('登录成功')
                nbK.run(name)
                break
            else:
                print('用户名密码不正确')
    
    
    def run():
        FUN_DIC = {
            '1':register,
            '2':login
        }
        while True:
            print('''
            请选择你的选项
            1——注册
            2——登录
            ''')
            select = input('请输入要选择的功能').strip()
            if not select.isdigit():
                print('请输入正确的选项')
            if not FUN_DIC.get(select):
                print('没有你要选择的功能')
            FUN_DIC[select]()
    run()
    
    客户端界面:
    import socket
    import struct
    import os
    soc = socket.socket()
    soc.connect(('127.0.0.1', 8080))
    user_dic = {'username':None}
    def uploading():
        soc.send(b'1')
        while True:
            fife_name = input('请输入你要上传的文件名,加后缀哦')
            if fife_name == 'q' or fife_name == 'Q':
                break
            if '.' not in fife_name:
                print('请重新输入你要上传的文件夹名')
                continue
            #传入用户长度
            user_len = struct.pack('i',len(user_dic['username']))
            soc.send(user_len)
            #传入用户名
            soc.send(bytes(user_dic['username'].encode('utf8')))
            #传入文件名长度
            fife_name_len = struct.pack('i',len(fife_name))
            soc.send(fife_name_len)
            # 传入文件名
            soc.send(bytes(fife_name.encode('utf8')))
            with open(fife_name,'rb') as fr:
                byts = fr.read()
            #传入数据长度
            b_len = struct.pack('i',len(byts))
            soc.send(b_len)
            # #传入数据
            soc.send(byts)
            print(f'上传文件{fife_name}成功')
    
    
    #下载文件
    def download():
        soc.send(b'2')
        while True:
            try:
                user_info_list = os.listdir(f'F:py9.10并发\user_name{user_dic["username"]}')
                for index,name in enumerate(user_info_list):
                    print(index+1,name)
                select = input('请选择你要下载的文件')
                if select == 'q' or select == 'Q':
                    break
                if len(user_info_list) < int(select):
                    print('没有你想要下载的文件')
                    continue
                # 传入用户长度
                user_len = struct.pack('i', len(user_dic['username']))
                soc.send(user_len)
                # 传入用户名
                soc.send(bytes(user_dic['username'].encode('utf8')))
                #获取文件名
                fife_name = user_info_list[int(select)-1]
                # 传入文件名长度
                fife_name_len = struct.pack('i', len(fife_name))
                soc.send(fife_name_len)
                # 传入文件名
                soc.send(bytes(fife_name.encode('utf8')))
                # 获取长度信息
                re_len = soc.recv(4)
                # 获取真正的长度
                l = struct.unpack('i', re_len)[0]
                # 进行数据拼接
                count = 0
                date_total = b''
                while count < l:
                    if l < 1024:  # 如果接受的数据小于1024 ,直接接受数据大小
                        data = soc.recv(l)
                    else:  # 如果接受的数据大于1024
                        if l - count >= 1024:  # 总数据长度-count(目前收到多少,count就是多少) 如果还大于1024  ,在收1024
                            data = soc.recv(1024)
                        else:  # 总数据长度-count(目前收到多少,count就是多少) 如果小于1024,只收剩下的部分就可
                            data = soc.recv(l - count)
                    date_total += data
                    count += len(data)
                with open(f'{fife_name}', 'wb') as fw:
                    fw.write(date_total)
                    print(f'下载文件{fife_name}成功')
            except Exception:
                print('请输入要下载的文件序号')
                continue
    
    
    
    #删除文件
    #########
    #偷懒写法#
    #########
    def delfife():
        while True:
            user_info_list = os.listdir(f'F:py9.10并发\user_name{user_dic["username"]}')
            for index, name in enumerate(user_info_list):
                print(index + 1, name)
            select = input('请选择你要删除的文件')
            if select == 'q' or select == 'Q':
                break
            if len(user_info_list)<int(select):
                print('没有你想要删除的文件')
            os.remove(f'F:py9.10并发\user_name{user_dic["username"]}{user_info_list[int(select)-1]}')
            print('删除成功')
    
    def run(name):
        FUN_DIC = {
            '1': uploading,
            '2': download,
            '3':delfife
        }
        user_dic['username'] = name
        while True:
            print('''
            请选择你需要的功能:
            1-上传文件
            2-下载文件
            3-删除文件
            ''')
            select = input('请输入要选择的功能:').strip()
            if select == 'q' or select == 'Q':
                break
            if not select.isdigit():
                print('请输入正确的选项')
            if not FUN_DIC.get(select):
                print('没有你要选择的功能')
            FUN_DIC[select]()
    
    服务器端
    import socketserver
    import struct
    user_dic = {'username':None}
    class Mytcp(socketserver.BaseRequestHandler):
        #重写handle方法
        def handle(self):
            try:
                while True:
                    select = self.request.recv(1)
                    select = int(select)
                    if select == 1:
                        print(self.client_address)
                        while True:
                            #用户名长度
                            age_len = self.request.recv(4)
                            if not age_len:
                                break
                            #用户名真正长度
                            age_l = struct.unpack('i',age_len)[0]
                            user_dic['username'] = self.request.recv(age_l).decode('utf8')
                            #文件名长度
                            fife_len = self.request.recv(4)
                            #文件名真正长度
                            fife_l = struct.unpack('i',fife_len)[0]
                            #读取文件名
                            fife_name = self.request.recv(fife_l).decode('utf8')
                            #获取长度信息
                            re_len = self.request.recv(4)
                            #获取真正的长度
                            l = struct.unpack('i',re_len)[0]
                            #进行数据拼接
                            count = 0
                            date_total =b''
                            while count < l:
                                if l < 1024:  # 如果接受的数据小于1024 ,直接接受数据大小
                                    data = self.request.recv(l)
                                else:  # 如果接受的数据大于1024
                                    if l - count >= 1024:  # 总数据长度-count(目前收到多少,count就是多少) 如果还大于1024  ,在收1024
                                        data = self.request.recv(1024)
                                    else:  # 总数据长度-count(目前收到多少,count就是多少) 如果小于1024,只收剩下的部分就可
                                        data = self.request.recv(l - count)
                                date_total += data
                                count += len(data)
                            with open(f'F:py9.10并发\user_name{user_dic.get("username")}{fife_name}','wb') as fw:
                                fw.write(date_total)
                    else:
                        while True:
                            # 用户名长度
                            age_len = self.request.recv(4)
                            if not age_len:
                                break
                            # 用户名真正长度
                            age_l = struct.unpack('i', age_len)[0]
                            user_dic['username'] = self.request.recv(age_l).decode('utf8')
                            # 文件名长度
                            fife_len = self.request.recv(4)
                            # 文件名真正长度
                            fife_l = struct.unpack('i', fife_len)[0]
                            # 读取文件名
                            fife_name = self.request.recv(fife_l).decode('utf8')
    
                            ##打开文件
                            with open(f'F:py9.10并发\user_name{user_dic["username"]}{fife_name}','rb') as fr:
                                byts = fr.read()
                                # 传入数据长度
                                b_len = struct.pack('i', len(byts))
                                self.request.send(b_len)
                                # #传入数据
                                self.request.send(byts)
    
    
    
                    #第一个参数是用于绑定地址,第二个参数传一个类
                    #ThreadingTCPServer自动开线程处理链接状态
            except Exception:
                pass
    
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),Mytcp)
        #一直监听
    server.serve_forever()
    
  • 相关阅读:
    AttributeError: module 'scipy.misc' has no attribute 'imread'
    3.形态学
    2.几何变换_图像金字塔
    ValueError:Object arrarys cannot be loaded when allow_pickle=False
    2.几何变换_切分合并通道
    2.几何变换_遮挡
    49. Group Anagrams
    151. Reverse Words in a String
    242. Valid Anagram
    227. Basic Calculator II
  • 原文地址:https://www.cnblogs.com/ledgua/p/11528787.html
Copyright © 2011-2022 走看看