• IO模型


    什么是IO模型?

    IO指的是输入输出,其执行速度非常慢

    模型,只固定的套路

    IO模型就是指实现输入输出的套路

    IO的分类

    1.本地IO 指的是输入输出到本地计算机 如:写入硬盘

    2.网络IO 指的是输入输出到网络中的计算机,速度远比本地IO慢

    网络IO输入输出过程

    IO模型的分类(重点)

    1.阻塞型IO

      之前学习的IO操作除了gevent都是阻塞型的

      1.可以利用多线程来提高IO

        线程不能太多,会造成内存溢出

      2.线程池可以解决下线程太多问题

        但如果线程池达到最大数,其他客户端将进入等待

      3.在单线程下并发来处理 可以使单核下的效率最高

    2.非阻塞IO

    非阻塞IO的服务器

    import socket
    server = socket.socket()
    server.bind(('192.168.1.67',4396))
    server.listen()
    #设置为非阻塞IO
    server.setblocking(False)
    #存放所有连接过来的客户端
    clients = []
    while True:
        try:
            client,addr = server.accept()
            print('连入了一个客户端!')
            clients.append(client)
        except BlockingIOError:
    
            #已经关闭的客户端
            close_c = []
            #将要回复的客户端以及数据
            msg_ls = []
            #接受数据循环
            for c in clients:
                try:
                    data = c.recv(1024)
                    if not data:
                        c.close()
                        close_c.append(c)
                    #不能直接发,因为操作系统缓存满了会抛出异常
                    msg_ls.append((c,data))
                except BlockingIOError:
                    pass
                except ConnectionResetError:
                    c.close()
                    close_c.append(c)
    
            #发送数据的循环
            #保存已发送的客户端和数据
            rm_msg = []
            for client_and_data in msg_ls:
                client = client_and_data[0]
                data = client_and_data[1]
                try:
                    client.send(data.upper())
                    #加入删除列表
                    rm_msg.append(client_and_data)
                except BlockingIOError:
                    pass
            
            #从将要回复的客户端和数据列表删除已经发送的成功客户端和数据
            for i in rm_msg:
                msg_ls.remove(i)
            #清空已经发送完成的客户端和数据列表
            rm_msg.clear()
            
            #从连入的客户端列表删除已经关闭的客户端列表
            for c in close_c:
                clients.remove(c)
            #清空已经关闭的客户端列表
            close_c.clear()
    

    非阻塞IO客户端

    import socket
    import os,time
    client = socket.socket()
    client.connect(('192.168.1.67',4396))
    while True:
        msg = 'hello i am:%s'%os.getpid()
        time.sleep(1)
        if not msg:
            continue
        client.send(msg.encode('utf-8'))
        data = client.recv(1024)
        print(data.decode('utf-8'))
    

    3.多路复用

    非阻塞IO对CPU占有率太高,为了解决这一问题我们使用多路复用

    什么是多路复用?

    多个连接复用一个线程 反过来说就是一个线程处理多个连接 提高了单线程的处理能力

    多路复用提高的是单线程处理网络IO的效率

    协程提升的是单线程处理所有IO的效率

     

    多路复用服务器:

    import socket,select
    server = socket.socket()
    server.bind(('192.168.1.67',4396))
    server.listen()
    #select 是帮我们监控连接
    #需要给他传两个参数列表,一个检测是否可读(是否可以执行recv),一个检测是否可写(是否执行send)
    rlist = [server,]
    wlist = []
    #默认select是阻塞的.直到其中有一个或几个需要被处理
    #存储要发送的数据
    msg = {}
    
    #返回值:
    #1.可读的连接(可以执行recv)
    #2.可写的连接(可以执行send)
    while True:
        readable_list,writeable_list,_ = select.select(rlist,wlist,[])
        #接下来处理可读可写的列表
    
        #处理可读的列表
        for c in readable_list:
            if c == server:#说明当要被处理的是服务器
                client,addr = server.accept()
                #把客户端交给select来检测是否可读
                rlist.append(client)
            else:
                print('客户端可以recv了!')
                data = c.recv(1024)
                print(data.decode('utf-8'))
                #将客户端也交给select来检测是否可写
                wlist.append(c)
                msg[c] = data
    
        #处理可写列表
        for w in writeable_list:
            w.send(msg[w].upper())
            #将已经发送完成的连接从检测列表删除
            wlist.remove(w)
    

    多路复用客户端:

    import socket,os,time
    client = socket.socket()
    client.connect(('192.168.1.67',4396))
    while True:
        msg = 'hello i am:%s'%os.getpid()
        time.sleep(1)
        if not msg:
            continue
        client.send(msg.encode('utf-8'))
        print(client.recv(1024).decode('utf-8'))
    

    4.异步IO

  • 相关阅读:
    Python __str__() 方法
    vim快捷键大全
    Python @函数装饰器及用法
    ImportError: No module named typing报错
    centos7安装pycharm2018专业版及破解
    windows下使用pycharm开发基于ansible api的python程序
    一个Windows系统下同时安装Python2和Python3
    django models def __str__(self)
    django model中的class Meta
    nmap命令详解
  • 原文地址:https://www.cnblogs.com/lizeqian1994/p/10265119.html
Copyright © 2020-2023  润新知