IO多路复用select ,pool ,epool之间的区别

IO多路复用select ,pool ,epool之间的区别

1.从跨平台来说。

1.select 跨平台性最好 效率一般 最多监控1024个IO
2.pool 跨平台一般 效率一般 监控IO无上限,水平触发。
3.epool 跨平台性差 效率高 监控IO无上限,边缘触发。
IO多路复用对比:

select优点:支持系统多   *  缺点:效率一般(相对以epool方法),最多监控1024
pool优点:监控IO数量没有限制。    缺点:效率一般(相对于epool方法),pool和select方法效率相当
epool优点:监控IO无限制,效率最高。    缺点:只支持Linux**

2.代码:

1.select方法

'''
IO多路复用
select方法
rs,ws,xs=select(rlist,wlist,xlist)参数分别是监管读IO 写IO  异步IO
1.套接字属于读IO同时也属于写IO,被动连接,主动发送消息
2.原理是select将监控的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',8888))
s.listen(5)
rlist=[s]
wlist=[]
xlist=[]
while True:
    # 循环监控s
    rs,ws,xs=select(rlist,wlist,xlist)#一个客户端连接s触发
    for r in rs:#[s,c,c,c.......]
        if r is s:
            # 又有客户端链接,处理完连接将跳到开头往下执行
            c,addr=r.accept()
            rlist.append(c)
    else:#如果是c将执行,r现在是c
        data=r.recv(1024).decode()
        if not data:#连接断开,连接断开返回一个空
            rlist.remove(r)#移除套接字
            r.close()
            continue#第一个退出不会影响后续客户端套接字
        print(data)
        wlist.append(r)
    for r in wlist:#wlist客户端发消息将就绪
        r.send(b'OK')
        wlist.remove(r)

2.pool方法

'''
poll完成tcp并发
'''
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( 3 )

#创建poll对象
p=poll()
p.register(s,POLLIN)#将s设置关注
#建立一个查找字典,用于通过文件描述父去查赵对象
fdmap={
     s.fileno():s}
while True:
    events=p.poll()#阻塞等待IO发生
    print(events)#[s.fileno(),s]
    for fd,event in events:
        #通过if结构区分哪个IO就绪,fd是文件描述符,evevt返回的是区别哪个事件的值,1是读,4是写,6是异步IO
        if fd==s.fileno():
            c,addr=fdmap[fd].accept()
            p.register(c,POLLIN)
            fdmap[c.fileno()]=c
        #客户端发消息则触发c
        elif event&POLLIN:#按位于判断是否为读事件,是就返回ture执行下边代码
            data=fdmap[fd].recv(1024).decode()#在这里fdmap[fd]是c客户端代码
            if not data:
                p.unregister(fd)#客户端退出则取消关注
                fdmap[fd].close()
                del fdmap[fd]#移除客户端套接字
                continue
            print(data)
            fdmap[fd].send(b'OK!')#返回给客户端一个消息

3.epool方法

'''

poll和epool除了名字不同外,其余代码都想同,内部实现完全不同。
'''
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( 3 )
ep=epoll()#创建pool对象
fdmap={
     s.fileno():s}
#关注套芥子
ep.register(s,EPOLLIN|EPOLLOUT)
#循环监控IO发僧

while True:
    events=p.poll()
    for fd,event in events:
        if fd == s.fileno():
            c,addr=s.accept()
            print('Counect from',addr)
            p.register(c,EPOLLIN|EPOLLERR)
            fdmap[c.fileno()]=c#注意维护字典与register保持一致
        elif event & EPOLLIN:
            #通过文件描述父获取对象
            data=fdmap[fd].recv(1024).decode()
            if not data:
                p.unregister(fd)#不再关注
                fdmap[fd].close()
                del fdmap[fd]#从字典删除
                continue
            print(data)
            fdmap[fd].send(b'ok')

3.从效率原理来说,下图片。

IO多路复用select ,pool ,epool之间的区别_第1张图片

你可能感兴趣的:(epoll,socket,python)