• IO多路复用


    定义:同时监控多个IO事件,当哪个IO事件准备就绪,就执行哪个IO事件,以此形成可用同时操作多个IO的并发行为,避免一个IO阻塞,造成所有的IO都无法执行
    IO准备就绪:是一种IO必然要发生的临界状态

    具体方案:
    select ---> windows linux unix
    poll ---> linux unix
    epoll ---> linux unix

    三种方案都在select模块中

    --------------------select------------------------------------

    rs, ws, xs = select(rlist, wlist, xlist[, timeout])
    功能:监控IO事件,阻塞等待IO事件发生
    参数:rlist 列表 存放我们监听等待处理的IO事件
       wlist 列表 存放我们要主动操作的IO事件
         xlist 列表 我们要关注出错处理的IO事件
         timeout 超时时间
    返回值:rs 列表 rlist中准备就绪的IO
        ws 列表 wlist中准备就绪的IO
        xs 列表 xlist中准备就绪的IO

    注意:
    * 在处理IO时不要形成死循环,让一个客户端单独占有服务端
    * IO多路复兴形成一种可以同时处理多个IO的效果,效率较高

    from select import select
    from socket import *
    
    s = socket()
    #端口的复用,当服务器关闭时,立马释放端口
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind(('0.0.0.0',10003))
    s.listen(5)
    
    
    rlist=[s]
    wlist=[]
    xlist=[]
    
    while True:
        #提交监测我们关注的IO等待IO发生
        rs, ws, xs = select(rlist, wlist, xlist)
        for r in rs:
            if r is s:
                c, addr = r.accept()
                print("Connect from",addr)
                rlist.append(c)   #添加到关注列表
            else:
                data = r.recv(1024)
                if not data:
                    rlist.remove(r)
                    r.close()
                else:
                    print(data.decode())
                    #将客户套接字放入wlist列表
                    wlist.append(r)
        for w in ws:
            w.send(b"Receive your message")
            wlist.remove(w)
    
        for x in xs:
            if x is s:
                s.close()

    ------------------------------poll--------------------------

    步骤
    1.创建poll对象
      p = select.poll()
    2.添加注册事件
      p.register(s)
      也可以移除注册事件
      p.unregister(s)
    3.阻塞等待IO发生
      events = p.poll()
      功能:阻塞等待IO发生
      返回值:events是一个列表,列表中每一个元素都是一个元组,代表一个发生的IO事件
      [(fileno, event),(),()......]
      就绪IO的文件描述符 具体就绪的事件
      **需要通过文件描述符(fileno)找到对应的IO对象
    4.处理具体的IO

    事件类别
      POLLIN     POLLOUT     POLLERR   POLLHUP     POLLPRI
      rlist      wlist      xlist   断开      紧急处理

    from socket import *
    from select import *
    
    #创建套接字做为我们关注的IO
    s = socket()
    
    s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
    s.bind(('0.0.0.0',10003))
    s.listen(5)
    
    #创建poll对象
    p = poll()
    
    #fileno ---> IO对象的字典
    fdmap = {s.fileno():s}
    
    #注册关注的IO
    p.register(s,POLLIN | POLLERR)
    
    while True:
        #进行IO监控
        events = p.poll()
        for fd,event in events:
            if fd == s.fileno():
                c,addr = fdmap[fd].accept()
                print("Connect from", addr)
                p.register(c,POLLIN | POLLHUP)
                fdmap[c.fileno()] = c
            elif event & POLLIN:  #利用事件来进行与运算,来判断是否有这事件
                data = fdmap[fd].recv(1024)
                if not data:
                    #客户端退出,从关注事件移除
                    p.unregister(fd)
                    fdmap[fd].close()
                    del fdmap[fd]
                else:
                    print(data.decode())
                    fdmap[fd].send(b"Receive")
  • 相关阅读:
    json-c初探(一)
    Java程序员跳槽的首选面试题最新合集(2021下半年),初中高级程序员!
    R语言版本的bedtools--bedtoolsr
    使用R语言(cpm包)进行序列变点(change point)检测
    三款PHP大马,已解密、去后门
    php 取出数据表数据放入数组并排序
    VimTutor每讲小结
    记录一下c++学习过程
    vmware fusion关闭自动挂起(suspend)的方法
    mac中安装mysqlclient出错error: command 'clang' failed with exit status 1的解决办法
  • 原文地址:https://www.cnblogs.com/zengsf/p/9607431.html
Copyright © 2020-2023  润新知