"""
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版权协议,转载请附上原文出处链接和本声明。