• IO模型 ---io多路复用(三)


    两者相互比较

    1、如果只有一个用户连接server端,多路复用IO还不如阻塞IO效率高

    2、相比阻塞IO,多路复用IO中间多了个反馈机制

    3、多路复用IO的代码可以同时监控socket、多个socket对象coon1 coon2....、 recv

    4、多路复用IO可以识别有人连接某个coon3,然后告知有coon3,然后coon3 recv

    5、可以不用while turn(占内存)去循环监听,直接有个代替我去做这些事

    6、多路复用IO机制是操作系统提供的,不是代码级别的,win下有专门提供多路复用IO机制select模块来完成【代理】的服务

    io多路复用

    server端

    import select
    import socket

    sk = socket.socket()
    sk.bind(('127.0.0.1',8000))
    sk.setblocking(False)
    sk.listen()

    read_lst = [sk]
    while True: # [sk,conn]
    r_lst,w_lst,x_lst = select.select(read_lst,[],[])
    for i in r_lst:
    if i is sk:
    conn,addr = i.accept()
    read_lst.append(conn)
    else:
    ret = i.recv(1024)
    if ret == b'':
    i.close()
    read_lst.remove(i)
    continue
    print(ret)
    i.send(b'goodbye!')

    client端

    import time
    import socket
    import threading
    def func():
    sk = socket.socket()
    sk.connect(('127.0.0.1',8000))
    sk.send(b'hello')
    time.sleep(3)
    print(sk.recv(1024))
    sk.close()

    for i in range(20):
    threading.Thread(target=func).start()

     

    这种并发是使用IO多路复用机制来实现并发的socket的server,并不是牺牲CPU的使用率来实现的,而是利用操作系统提供的IO多路复用的机制

    # IO多路复用(在win下并不是很高效)
        # select机制   Windows 和 linux 都有     都是操作系统轮询每一个被监听的项,看是否有读操作
        #     poll机制     linux          它可以监听的对象比select机制可以监听的多
                                                 # 随着监听项的增多,导致效率降低


        #     epoll机制   linux    对每一个列表监听的对象绑定一个回调函数,回调函数来反馈有人来链接(Linux下推荐使用)

    为了代码的可用于适用不同系统机制,出现selector,根据系统自动选择对于的IO多路复用机制(selector_demo)

    import selectors
    from socket import *

    def accept(sk,mask):
    conn,addr=sk.accept()
    sel.register(conn,selectors.EVENT_READ,read)

    def read(conn,mask):#一般使用我们只需要变动这段内容就好,其他不用变
    try:
    data=conn.recv(1024)
    if not data:
    print('closing',conn)
    sel.unregister(conn)
    conn.close()
    return
    conn.send(data.upper()+b'_SB')
    except Exception:
    print('closing', conn)
    sel.unregister(conn)
    conn.close()

    sk=socket()
    sk.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    sk.bind(('127.0.0.1',8088))
    sk.listen(5)
    sk.setblocking(False) #设置socket的接口为非阻塞
    sel=selectors.DefaultSelector() # 选择一个适合我的IO多路复用的机制
    sel.register(sk,selectors.EVENT_READ,accept)
    #相当于网select的读列表里append了一个sk对象,并且绑定了一个回调函数accept
    # 说白了就是 如果有人请求连接sk,就调用accept方法

    while True:
    events=sel.select() #检测所有的sk,conn,是否有完成wait data阶段,这里没SK对象是阻塞,当有SK对象时走下面的for
    for sel_obj,mask in events: # [SK] [conn]
    callback=sel_obj.data #callback=read
    callback(sel_obj.fileobj,mask) #read(conn,1)


    站在python角度,不太好实现异步框架,因为在copy date阶段未提供对于python接口

     

    当我们web开发server端时,如果预计可能每秒的访问量比较大时,这时候我们就不要选择diango框架(非异步框架),应该选择 tornade(或 twstied)异步IO框架(没有wait date和copy date阻塞阶段,能响应更多的请求)

  • 相关阅读:
    位运算一些简单的应用
    运算符的优先级
    Vue.js 指南-基础
    Nginx将项目配置在子目录
    JavaScript创建读取cookie代码示例【附:跨域cookie解决办法】
    JavaScript动态加载资源【js|css】示例代码
    Uploadifive 使用教程【结合七牛】
    mac 配置快捷键快速锁屏
    七牛大文件上传同步工具配置
    使用七牛云存储作为图床
  • 原文地址:https://www.cnblogs.com/mys6/p/10920198.html
Copyright © 2020-2023  润新知