zoukankan      html  css  js  c++  java
  • Python正课93 —— IO模型

    本文内容皆为作者原创,如需转载,请注明出处:https://www.cnblogs.com/xuexianqi/p/12797277.html

    一:IO模型简洁

    * blocking IO           阻塞IO
    * nonblocking IO      非阻塞IO
    * IO multiplexing      IO多路复用
    * asynchronous IO    异步IO
    	由于 signal driven IO(信号驱动IO)不常用,所以主要介绍其余4种
    
    1.等待数据准备(Waiting for the data to be ready)
    2.将数据从内核拷贝到进程中(Copying the data from the kernel to the process)
    

    001

    同步异步
    阻塞非阻塞
    常见的网络阻塞状态:
    	accept
    	recv
    	recvfrom
    	
    	send虽然它也有IO行为 但是不在我们的考虑范围
    

    二:阻塞IO

    005

    我们之前写的都是阻塞IO模型	协程除外
    
    import socket
    
    server = socket.socket()
    server.bind(('127.0.0.1', 8080))
    server.listen(5)
    
    while True:
        conn, addr = server.accept()
        while True:
            try:
                data = conn.recv(1024)
                if len(data) == 0:
                    break
                print(data)
                conn.send(data.upper())
    
            except ConnectionResetError as e:
                print(e)
        conn.close()
        
    # 在服务端开设多进程或者多线程,进程池线程池,其实还是没有解决IO问题
    该等的地方还是得等 没有规避
    只不过多个人等待的时候 彼此互不干扰
    

    三:非阻塞IO

    003

    服务端:

    import socket
    import time
    
    
    server = socket.socket()
    server.bind(('127.0.0.1', 8081))
    server.listen(5)
    server.setblocking(False)
    # 将所有的网络阻塞变为非阻塞
    r_list = []
    del_list = []
    while True:
        try:
            conn, addr = server.accept()
            r_list.append(conn)
        except BlockingIOError:
            # time.sleep(0.1)
            # print('列表的长度:',len(r_list))
            # print('做其他事')
            for conn in r_list:
                try:
                    data = conn.recv(1024)  # 没有消息 报错
                    if len(data) == 0:  # 客户端断开链接
                        conn.close()  # 关闭conn
                        # 将无用的conn从r_list删除
                        del_list.append(conn)
                        continue
                    conn.send(data.upper())
                except BlockingIOError:
                    continue
                except ConnectionResetError:
                    conn.close()
                    del_list.append(conn)
            # 挥手无用的链接
            for conn in del_list:
                r_list.remove(conn)
            del_list.clear()
    

    客户端:

    import socket
    
    
    client = socket.socket()
    client.connect(('127.0.0.1',8081))
    
    
    while True:
        client.send(b'hello world')
        data = client.recv(1024)
        print(data)
    

    总结:

    虽然非阻塞IO给你的感觉非常牛逼
    但是该模型会 长时间占着CPU不用  让CPU不停的空转 占着茅坑不拉屎
    我们实际应用中也不会考虑使用非阻塞IO模型
    
    任何的技术点都有它存在的意义 
    实际应用或者是思想借鉴
    

    四:IO多路复用

    002

    当监管的对象只有一个的时候 其实IO多路复用连阻塞IO都比比不上!!!
    但是IO多路复用可以一次性监管很多个对象
    
    server = socket.socket()
    conn,addr = server.accept()
    
    监管机制是操作系统本身就有的 如果你想要用该监管机制(select)
    需要你导入对应的select模块
    

    服务端:

    import socket
    import select
    
    
    server = socket.socket()
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    server.setblocking(False)
    read_list = [server]
    
    
    while True:
        r_list, w_list, x_list = select.select(read_list, [], [])
        """
        帮你监管
        一旦有人来了 立刻给你返回对应的监管对象
        """
        # print(res)  # ([<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080)>], [], [])
        # print(server)
        # print(r_list)
        for i in r_list:  #
            """针对不同的对象做不同的处理"""
            if i is server:
                conn, addr = i.accept()
                # 也应该添加到监管的队列中
                read_list.append(conn)
            else:
                res = i.recv(1024)
                if len(res) == 0:
                    i.close()
                    # 将无效的监管对象 移除
                    read_list.remove(i)
                    continue
                print(res)
                i.send(b'heiheiheiheihei')
    

    客户端:

    import socket
    
    
    client = socket.socket()
    client.connect(('127.0.0.1',8080))
    
    
    while True:
    
        client.send(b'hello world')
        data = client.recv(1024)
        print(data)
    

    总结:

    监管机制其实有很多
    select机制  windows linux都有
    
    poll机制    只在linux有   poll和select都可以监管多个对象 但是poll监管的数量更多
    
    上述select和poll机制其实都不是很完美 当监管的对象特别多的时候
    可能会出现 极其大的延时响应
    
    epoll机制   只在linux有
       它给每一个监管对象都绑定一个回调机制
       一旦有响应 回调机制立刻发起提醒
    
    针对不同的操作系统还需要考虑不同检测机制 书写代码太多繁琐
    有一个人能够根据你跑的平台的不同自动帮你选择对应的监管机制
    selectors模块
    

    五:异步IO

    004

    异步IO模型是所有模型中效率最高的 也是使用最广泛的
    相关的模块和框架
       模块:asyncio模块
       异步框架:sanic tronado twisted
          速度快!!!
    
    import threading
    import asyncio
    
    
    @asyncio.coroutine
    def hello():
        print('hello world %s'%threading.current_thread())
        yield from asyncio.sleep(1)  # 换成真正的IO操作
        print('hello world %s' % threading.current_thread())
    
    
    loop = asyncio.get_event_loop()
    tasks = [hello(),hello()]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()
    

    六:四个IO模型对比

    005

    003

    002

    004

    七:总结

    网络并发知识点梳理:

    1.软件开发架构	B/S;C/S
    
    2.互联网协议
        OSI七层协议
        五层
        每一层都是干嘛的
            以太网协议	广播风暴
            IP协议
    
            TCP/UDP
    
    3.三次握手、四次挥手
    
    4.Socket简洁
    
    5.TCP粘包问题	定制固定长度的包头
    
    6.UDP协议
    
    7.SocketServer模块
    

    并发编程

    1.操作系统发展史
    
    2.多道技术
    
    3.进程理论
    
    4.开启进程的2种方式
    
    5.互斥锁
    
    6.生产者消费者模型
    
    7.线程理论
    
    8.开启线程的2种方式
    
    9.GIL全局解释器锁
    
    10.进程池 线程池
    
    11.协程的概念
    
    12.IO模型
    
  • 相关阅读:
    T-sql for xml path使用
    解决 SQL Server2012附加出错的问题
    安装应用程序 报“ 997 重叠 I/O 操作在进行中”错解决办法
    使用QQ互联登录应用
    monogdb windows环境下 安装及使用简单示例
    idle-实现清屏
    colorscheme-如何vim颜色风格
    android-从官网下拉源码(ubuntu)
    hq-源码编译
    文件目录进入终端
  • 原文地址:https://www.cnblogs.com/xuexianqi/p/12797277.html
Copyright © 2011-2022 走看看