IO多路复用(select,poll ,epoll 编程)

一、IO input output

          在内存中存在数据交换的操作都可以认为是IO操作

          和终端交互:input    print

           和磁盘交互: read     write

          和网络交互:recv    send

     IO密集型程序:在程序执行过程中存在大量IO操作,而cpu运算操作较少。消耗cpu较少,运行效率较低

     计算密集型程序(cpu密集型程序):在程序执行中cpu运算较多,IO操作相对较少。消耗cpu大,运行速度快

二、 IO分类:

       阻塞IO     非阻塞IO     IO多路复用

1、阻塞IO:是IO的默认形态,是效率较低的一种IO情形。

阻塞情况:

1)因为某种条件没有达成造成的阻塞

eg: accept input recv

2)处理IO数据传输时间较长形成的阻塞

e g: 网络传输过程,文件读写过程

2、非阻塞IO:是指通过修改IO事件的属性,使其变为非阻塞状态(让一些条件阻塞函数不再阻塞)

  *非阻塞IO往往和循环判断一起使用

   s.setblocking(False)

   将套接字设置为非阻塞状态

     超时检测

将原本阻塞的函数设置一个最长阻塞时间,如果时间内条件达成则正常运行,如                                               果任然阻塞则视为超时继续向下运行或产生异常

  s.settimeout(sec)  设置套接字的超时时间

三、IO多路复用

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

IO准备就绪:就是一种IO必然要发生的临界状态

IO多路复用的编程实现:

         1、将IO设置为关注IO

         2、将关注IO 提交给内核检测

         3、处理内核给我们反馈的准备就绪的IO

具体方案:

select ------> windows linux nuix

poll --------> linux unix

epoll  -------> linux unix

   **<1>   import 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 
       注意:
             1、wlist中如果有IO事件则select立即返回ws
            2、在处理IO过程中不要处理一个客户端长期占有服务端使服务端无法运行到select的情况
            3、IO多路复用占用计算机资源少,IO效率高**

  <2>

     位运算:整数按照二进制位进行运算

      &   按位与       |   按位或     ^ 按位异或

     <<      左移             >> 右移

    11   1011

    14   1110

    &:11&14    10   1010(一0则0)

     |:             15     1111(一1 则1)

    ^ :             5       0101(相同为0,不同为1)

    <<:11<<2    44     101100(左移2位右边补0)

   >>:14>>2     2       11       (右移2位左边补两位)

**poll**

    1、创建poll对象

      p = select.poll()

    2、添加注册事件

      p.register(s,POLLIN  |  POLLERR)



      POLLIN     POLLOUT     POLLERR    POLLHUP    POLLNVAL

        ^                ^                    ^                          ^                ^

       rlist            wlist              xlist                  断开          无效数据

      p.unregister(s)从关注事件中移除

    3、阻塞等待IO发生

       events = p.poll()

         功能:阻塞等待IO发生

返回值:events 是一个列表,列表中每一个元素都是一个元组,代表一个发生的IO事件

        [(fileno,                                   event),                (),(),...]

        就绪IO的文件描述符          具体就绪事件

      **需要通过文件描述符(fileno)找到对应的IO对象

               {s.fileno():s}

    4、处理具体的IO

epoll方法:

       使用方法:基本与poll方法相同

      *将生产对象poll()改为e poll()

     *将所有poll对象事件改为epoll对象事件

 区别:

   epoll的效率要比poll和select高

  epoll的事件触发方式更多

本地套接字

linux文件

       b(块设备文件)     c(字符设备文件)     d(目录)

       s(套接字)            p(管道)

作用:

    2、绑定本地套接字文件

             *选定文件位置和名称

             *sockfd.bind(path)

  3、监听  listen()

  4、消息收发,recv     send

cookie:

    os.path.exists(path)

    功能:判断一个文件是否存在

    参数:目标文件

    返回值:存在返回True  否则返回False        

   os.remove()   os.unlink()

   功能:删除一个文件

   参数:目标文件

Select 示例代码:

**from select import select
from socket import *

#创建套接字作为我们关注的IO
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('0.0.0.0',8888))
s.listen(5)

rlist = [s]
wlist = []
xlist = [s]

while True:
    #提交监测我们关注的IO等待IO发生
    rs,ws,xs = select(rlist,wlist,xlist)
    for r in rs:
        if r is s:
            c,addr = rs[0].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())
                #r.send(b'Receive your message')
                #将客户端 套接字放入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 示例代码:

**from socket import *
from select import *

#创建套接字作为我们关注的IO
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('0.0.0.0',8888))
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 your message')**

Epoll示例代码:

**from socket import * 
from select import *

#创建套接字作为我们关注的IO
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('0.0.0.0',8888))
s.listen(5)

#创建epoll对象
p = epoll()

#fileno ---> IO对象的字典
fdmap = {s.fileno():s}

#注册关注的IO
p.register(s,EPOLLIN | EPOLLERR)

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,EPOLLIN | EPOLLHUP)
            fdmap[c.fileno()] = c
        elif event & EPOLLIN:    
            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')**
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值