IO模型

内容概要

  • IO模型介绍
  • 阻塞IO模型
  • 非阻塞IO模型
    • 理论
    • 代码演示
  • IO多路复用
  • asyncio模块
  • IO模型总结
  • 网络并发复习

内容详细

  • IO模型介绍

    '''
    Stevens在文章中一共比较了五种IO Model:
        * blocking IO           阻塞IO
        * nonblocking IO      非阻塞IO
        * IO multiplexing      IO多路复用
        * signal driven IO     信号驱动IO
        * asynchronous IO    异步IO
        由signal driven IO(信号驱动IO)在实际中并不常用,所以主要介绍其余四种IO Model
    '''
    #1)等待数据准备 (Waiting for the data to be ready)
    #2)将数据从内核拷贝到进程中(Copying the data from the kernel to the process)
    
    同步异步
    阻塞非阻塞
    常见的网络阻塞状态:
    	accept
        recv
        recvfrom
        
        send虽然它也有IO行为,但是不在我们的考虑范围(主动发送,显得很快仿佛没有IO)
    
  • 阻塞IO模型

    '''
    我们之前写的都是阻塞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)
                server.send(data.upper())
            except ConnectionResetError as e:
                break
        conn.close()
        
    # 在服务端开设多进程或者多线程 进程池线程池 其实还是没有解决IO问题
    该等的地方还是得等 没有规避
    只不过多个人等待的彼此互不干扰
    
  • 非阻塞IO模型

    '''
    要自己实现一个非阻塞IO模型
    '''
    
    # 服务端
    import socket
    
    
    server = socket.socket()
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    server.setblocking(False)
    # 将所有的网络阻塞变成非阻塞
    
    r_list = []
    del_list = []
    while True:
        try:
            conn,addr = server.accept()
            r_list.append(conn)
        except BlockingIOError as e:
            # print('做其他事')
            # print('列表长度:',len(r_list))
            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  # r_list中conn有没有消息,没有下一个,如果都没消息,与server.accept()来回切换
                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',8080))
    
    while True:
        client.send(b'hello world')
        data = client.recv(1024)
        print(data)
    

    总结

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

    '''
    当监管的对象只有一个的时候,其实IO多路复用连阻塞IO都比不上
    但是IO多路复用可以一次性监管很多个对象
    
    server = socket.socket()
    conn,addr = server.accpet
    
    监管机制是操作系统本身就有的  如果你想要用该监管机制(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(r_list)
        '''
        [<socket.socket fd=292, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080)>]
        [<socket.socket fd=128, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 58909)>]
        '''
        # print(server)
        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'heihei')
    
                
    # 客户端
    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(asyncio模块)

    '''
    异步IO模型是所有模型中效率最高的 也是使用最广泛的
    相关的模块和框架
    	模块:asyncio模块
    	异步框架:sanic tronado twisted
    		速度快!!!
    '''
    
    import threading
    import asyncio
    # 能实现异步,能在单线程下实现并发(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()
    
  • 四个模型对比

    参考博客园图解,稍微了解即可

    总结

    每个模型要用自己的话去总结一下
    
  • 网络并发复习

    1.软件开发结构

    2.互联网协议

    '''osi七层五层每一层都是干嘛的	以太网协议  广播风暴	IP协议		TCP/UDP'''
    

    3.三次握手四次挥手(******)

    4.socket简介

    5.TCP粘包问题 定制固定长度的报头

    6.UDP协议

    7.socketserver模块

​ 操作系统发展史

​ 多道技术

​ 进程理论

​ 开启进程的两种方式

​ 互斥锁

​ 生产者消费者模型

​ 线程理论

​ 开启线程的两种方式

posted @ 2021-07-22 15:34  ccFTD  阅读(72)  评论(0)    收藏  举报