• 并发编程5


    IO模型

    五种IO模型
       * blocking IO           阻塞IO
        * nonblocking IO      非阻塞IO
        * IO multiplexing      IO多路复用
       * signal driven IO     信号驱动IO
        * asynchronous IO    异步IO
        由signal driven IO(信号驱动IO)在实际中并不常用,所以主要介绍其余四种IO Model。
       同步异步
    阻塞非阻塞
    常见的网络阻塞状态:
    accept
        recv
        recvfrom
       
        send虽然它也有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)
                conn.send(data.upper())
            except ConnectionResetError as e:
                break
        conn.close()
       
    '''
    在服务端开设多进程或者多线程 进程池线程池 其实还是没有解决IO问题
    该等的地方还是得等 没有规避
    只不过多个人等待的彼此互不干扰
    '''
    非阻塞型IO

    如何自己实现非阻塞型IO

    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)

    PS:虽然非阻塞IO给人的感觉非常顺滑~,但是非阻塞型IO会长时间占用CPU,使得CPU不停的空转,因此在实际应用中也不会使用到非阻塞型IO

    IO多路复用
    '''
    IO多路复用,听名字就知道肯定是多个对象。
    在监管一个对象时IO多路复用甚至连阻塞IO都不如
    但时IO多路复用可以监管多个对象
    监管机制是操作系统本身就有的 如果你想要用该监管机制(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)

    PS:在不同的平台有不同的监管机制,相对的监管数量也有差异

    但是selectors模块可以根据你程序运行的不同平台帮你选择对应的监管机制

    异步IO
    '''
    异步IO是所有所有模型中效率最高,并且是应用最广泛的一种
    模块与框架——asyncio模块
    ——sanic tronado twisted异步框架
    '''
    asyncio模块
    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()

  • 相关阅读:
    ActiveMQ 默认用户名和密码
    # ActiveMQ连接超时问题(java.net.SocketException: Connection reset)
    SpringBoot(十) Logback 配置详解
    postgresql10以上的自动分区分表功能
    基于Redis实现延时队列服务
    Redis(十三):Redis分布式锁的正确实现方式
    Redis(十七):批量操作Pipeline
    Redis(十八):Redis和队列
    PostgreSQL SELECT INTO和INSERT INTO SELECT 两种表复制语句
    PostgreSQL 从文件时间戳获悉一些信息(如数据库创建时间)
  • 原文地址:https://www.cnblogs.com/bailongcaptain/p/12794807.html
Copyright © 2020-2023  润新知