python中IO多路复用之epoll模型

"""
epoll  :   linux
            1.创建epoll对象       p=select.epoll()
            2.注册关注的IO事件     p.register(fd,event)
                                p.register(sockfd,POLLIN|POLLERR)
            3.取消对IO的关注      p.unregister(fd)  fd:IO对象或者IO对象的fileno
            4.阻塞等待监控的IO事件发生     events=p.epoll()
                                    返回的是元组格式[(fileno,event),()...] 文件描述符和事件类型

            1.方法与poll相同,将poll改为epoll
            2.效率比select,poll高
            3.监控的IO数量比select要多
            4.触发方式比poll要多(EPOLLET边缘触发,默认水平触发)
        边缘触发:事件触发后,可以不回应,可以和下一次的事件一起做出回应
        水平触发:事件触发后,必须要做出回应,
        注意: epoll不能重复注册register(poll重复注册只是覆盖,epoll是开辟一块新空间,再次注册空间已经有会报错)

"""

from socket import *
import select

# 创建tcp套接字
soc = socket(AF_INET, SOCK_STREAM)
# 开启端口立即重用
soc.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
# 绑定服务器地址
soc.bind(("127.0.0.1", 9090))
# 开启监听服务
soc.listen(3)
# 创建字典,并以套接字描述符为键,套接字为值,添加字典对象
# 始终与register的IO保持一致
dic = {soc.fileno(): soc}

# 创建poll对象
ep = select.epoll()
# 加入关注,并监控读取事件发生
ep.register(soc, select.EPOLLIN)
print("waiting connect ...")
# 循环等待接收客户端连接请求
while True:
    # 阻塞等待IO事件发生(返回值是一对对元组组成(IO描述符,监控事件类型))
    event = ep.poll()
    # 循环遍历列表,查看那个IO就绪,就处理
    for so, even in event:
        # 区分那个IO就绪
        if so == soc.fileno():
            c, addr = dic[so].accept()
            print("connect from ", addr)
            # 关注客户端连接套接字
            ep.register(c, select.EPOLLIN | select.EPOLLERR)
            # 维护字典,更新数据
            dic[c.fileno()] = c
        elif even & select.EPOLLIN:
            data = dic[so].recv(1024).decode()
            if not data:
                # 取消对IO的关注
                ep.unregister(so)
                # 关闭IO套接字
                dic[so].close()
                # 从字典中移除
                del dic[so]
                continue
            print("c>>", data)
            dic[so].send(b"OK")

版权声明:本文为qq_43513797原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。