Python:python中IO多路复用使用

IO多路复用

  • 大多数操作系统都是支持select和poll
  • Linux2.5+ 支持epoll
  • BSD、Mac支持kequeue
  • Windows的IOCP

Python的select库
实现了select、poll系统调用,这个基本上操作系统都是支持。部分实现了epoll。
底层的IO多路复用模块

开发中的选择
1、完全跨平台、使用select、poll。但是性能较差 
2、针对不同操作系统自行选择支持的技术,这样做会提高IO的处理能力                                                

Selects库、执行选择支持的IO技术 

3.4版本提供这个库,高级IO复用库

#类层结构
BaseSelector
+ ----      SelectSelector   实现Select
+ ----      PollSelector     实现poll
+ ----      EpollSelector    实现epoll
+ ----      DevpollSelector  实现devpoll
+ ----      KqueueSelector   实现kqueue

selectors.DefaultSelector 返回当前平台最有效、性能最高的实现。但是,由于没有实现Windows下的IOCP,所以退化为select


#在select模块源码最下面有如下代码
# Choose the best implementation, roughly:
#    epoll|kqueue|devpoll > poll > select.
# select() also can't accept a FD > FD_SETSIZE (usually around 1024)
if 'KqueueSelector' in globals():
    DefaultSelector = KqueueSelector
elif 'EpollSelector' in globals():
    DefaultSelector = EpollSelector
elif 'DevpollSelector' in globals():
    DefaultSelector = DevpollSelector
elif 'PollSelector' in globals():
    DefaultSelector = PollSelector
else:
    DefaultSelector = SelectSelector

abstractmethod.register(fileobj,events,data=None):为select注册一个文件对象,监控它的IO事件。

  • fileobj:被监控文件对象,例如socket对象
  • events事件,该文件对象必须等待的事件
  • data可选的与此文件对象相关联的不透明数据,例如:关联用来存储每个客户端的会话ID,关联方法。通过这个参数在关注的事件产生后让select干什么事
Event常量含义
EVENT_READ可读ob01,内核已经准备好输入输出设备,可以开始读了
EVENT_WRITE可写ob10,内核准备好了,可以往里写了

代码

import selectors
import threading
import socket
import logging


FORMAT = "%(asctime)s  %(threadName)s %(thread)d %(message)s"
logging.basicConfig(format=FORMAT,level=logging.INFO)

#构建缺省性最优selector
selector = selectors.DefaultSelector()
#回调函数,自己定义形参


def accept(sock:socket.socket ):
    "mask : 事件掩码的或值"
    conn , cleint = sock.accept() #阻塞等待连接进来
    conn.setblocking(False)  #准备为每一个客户端建立单独的sock对象
    #监视conn这个文件对象
    selector.register(conn,selectors.EVENT_READ,recv)
    logging.info(key)

#回调函数
def recv(conn:socket.socket):
    data = conn.recv(1024)
    msg = "Your msg is {}".format(data.decode())
    conn.send(msg.encode())




#创建TCP连接
sock = socket.socket()  #创建socket对象
sock.bind(("127.0.0.1",9990))
sock.listen()
logging.info(sock)
sock.setblocking(False)  #非阻塞

e = threading.Event()
print(threading.enumerate())
#注册selector 中监听的对象,事件和回调的data,返回selecttorKey
#将sock、关注事件、data都绑定到key实例属性上
key = selector.register(sock,selectors.EVENT_READ,accept)
logging.info(key)
print(key)


def select(e):
    while not e.is_set():
        #开始监听,等到有文件对象监控事件产生,返回(key,mask)元组
        events = selector.select()
        if events:
            print("1111",events)
        for key ,mask in events:
            call_back = key.data   #accept 或者 recv
            call_back(key.fileobj)
            print("kkkkkkkk",key,"mmmmmm",mask)
threading.Thread(target=select,args=(e,),name="select").start()
def main():
    while not e.is_set():
        cmd = input(">>>")
        if cmd.strip() == "quit":
            e.set()
            fobjs = []
            logging.info("{}".format(selector.get_map().items()))
            for fd,key in selector.get_map().items():
                print(22222222222222222,fd,key)
                print(key.fileobj)
                fobjs.append(key.fileobj)
            for bobj in fobjs:
                selector.unregister(bobj)
                bobj.close() #关闭socket
            selector.close()

if __name__ == '__main__':
    main()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值