Python实现IO多路复用

IO多路复用定义:同时监控多个IO事件,当哪个IO事件准备就绪就执行哪个IO。
以此形成可以同时处理多个IO的行为,避免一个IO阻塞造成其他IO无法执行的情况,提高了IO执行效率。

具体执行方案:

	1.	select : windows  linux   unix
	2.	 poll : linux  unix
	3.	 epoll : linux 

1.select 方法
rs,ws,xs=select(rlist,wlist,xlist,[timeout])
功能:监控多个IO事件,阻塞等待IO发生,
参数: rlist 列表 存放的关注等待发生的IO事件
wlist列表:存放要主动处理的IO事件
xlist列表:存放发生异常时要处理的IO
timeout 超时时间

     * wlist中如果有IO事件,则select会立即返回给ws
	* 处理IO事件过程中不要出现死循环等长期占有服务端情况
	* IO多路复用消耗资源较少,效率较高

1.select_server.py

from select import select
from socket import *
#创建套接字作为关注的IO
s=socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
#绑定地址
s.bind(('0.0.0.0',9610))
#设置监听
s.listen(3)
#将套接字添加到关注列表
rlist=[s]
wlist=[]
xlist=[]
#循环监控IO
while True:
	rs,ws,xs=select(rlist,wlist,xlist)
	遍历监听列表
	for r in rs:
		#s就绪说明有客户端连接
		if r is s:
			#建立连接
			c,addr=r.accept()
			print("Connect addr:"addr)
			#将客户端套接字加入监听列表
			rlist.append(c)
			#如果是c则表示对应的客户端发送消息
		else:
			data=r.recv(1024)
			if not data: #如果客户端退出,则将对应的套接字从监听列表中移除
				rlist.remove(r)
				r.close()
			print(data.decode())
			#把r放入wlist中表示希望主动处理
			wlist.append(r)
    for w in ws:
    	w.send(b'ok')
    	wlist.remove(w)
    for in xs:
    	pass`

 2.epoll方法实现:
from select import *
from socket import *
#创建需要被关注的IO对象
s=socket()
#设置允许在同一端口的同一服务器上使用多个实例
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
#绑定地址
s.bind(('0.0.0.0',9610))
#设置监听
s.listen(5)
#创建epoll对象
p=epoll()

#建立地图
fdmap={s.fileno():s}

#设置IO关注
p.register(s,EPOLLIN|EPOLLERR)
#循环监控IO:
while True:
	events=p.poll()
	print("你有要处理的IO哦")
	#遍历events 处理IO
	for fd,event in events:
		if fd==s.fileno():
			
			c,addr=fdmap[fd].accept()
			print("Connect from :"addr)
			#添加新的关注IO
			p.register(c,EPOLLIN|EPOLLHUP|EPOLLET)
			fdmap[c.fileno()] = c 
		elif event & EPOLLHUP: #如果监控到的事件EPOLLHUP则执行操作
            print("客户端退出")
            p.unregister(fd)
            fdmap[fd].close()
            del fdmap[fd]
        #elif event & EPOLLIN:
          #   data = fdmap[fd].recv(1024)
            #print(data.decode())
            #fdmap[fd].send(b'OK')

3.poll实现方法(与epoll实现方法非常的类似)
from select import * 
from socket import * 

# 创建关注的IO
s = socket()
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('0.0.0.0',8888))
s.listen(5)

# 创建poll对象
p = poll()

# 建立地图
fdmap = {s.fileno():s}

# 关注IO
p.register(s,POLLIN|POLLERR)

# 循环监控IO
while True:
    events = p.poll() 
    # 遍历events 处理IO
    for fd,event in events:
        if fd == s.fileno():
            c,addr = fdmap[fd].accept()
            print("Connect from",addr)
            # 添加新的关注IO
            p.register(c,POLLIN|POLLHUP)
            fdmap[c.fileno()] = c  
        elif event & POLLHUP:
            print("客户端退出")
            p.unregister(fd)
            fdmap[fd].close()
            del fdmap[fd]
        elif event & POLLIN:
            data = fdmap[fd].recv(1024)
            print(data.decode())
            fdmap[fd].send(b'OK')

注意:select、epoll、poll 实现IO多路复用的核心思想都是一样的,此处所指的均是流式套接字。将服务端套接字加入监听,当顺利连接客户端后,将客户端套接字加入监听行里,每次有新的客户端连接时,就加入监听队列中。服务端套接字用于进行客户端的连接,客户端套接字,用于和客户端进行消息的收发操作。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值