Python Epoll 异步多路复用 详解
1.3 Python IO复用之epoll
触发方式:
边缘触发/水平触发
只适用于Unix/Linux操作系统
原理图:
点集:
select.EPOLLIN 对应 1
select.EPOLLOUT 对应 4
select.EPOLLHUP 对应 16
用法:
import select
导入select模块
epoll = select.epoll()
创建一个epoll对象
epoll.register(fileno,event)
注册要监控的文件句柄到epoll 相关事件ID(比如“读”事件:EPOLLIN 对应 1)进行监听
event_type:
select.EPOLLIN 监听读事件
select.EPOLLOUT 监听写事件
select.EPOLLERR 监听错误事件
select.EPOLLHUP 监听断开状态
epoll.unregister(fileno)
销毁文件描述符,不再进行监听
epoll.poll(-1)
当文件描述符发生改变则会以列表的形式主动报告给用户进程,timeout为获取结果的时间单位为秒 当timeout等于-1的时永远等待(默认就是-1)直到文件描述符发生改变,如果指定为1那么epoll每1秒进行汇报一次当前文件描述符的状态那怕是没有文件描述符发生改变也会返回一个空值
epoll.fileno()
返回epoll的控制文件描述符
epoll.modfiy(fineno,event)
fineno 文件描述符
event 各式的epoll常数点集
将当前文件描述符转移到指定的一个点集
epoll.fromfd(fileno)
创建一个epoll fileno文件描述符,从一个给定的控制对象
epoll.close()
关闭epoll控制,对象将引发异常
实例:
客户端发数据 服务端将数据返回 客户端接收
Epoll Server:
#!/usr/bin/env python #-*- conding:utf8 -*- import socket import select #创建socket文件句柄 server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #设置socket为ip address复用 server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #将socket句柄绑定到本机的1234端口 server.bind(('0.0.0.0',1234)) #监听最大个数10个 server.listen(10) #设置非阻碍模式 server.setblocking(0) #创建一个epoll对象 epoll=select.epoll() #注册socket文件句柄到 select.EPOLLIN点集 epoll.register(server.fileno(),select.EPOLLIN) #测试代码不用鸟他 print 'server filno:',server.fileno() #创建字典来存储 连接 请求 connections={};requests={};responses={} while True: #将epoll将发生改变的文件句柄回调到用户进程 用events暂存此数据 events=epoll.poll() #将文件句柄 和 时间状态从events数据提出来 events = [(文件句柄,时间状态ID)] for fileno,event in events: #判断是否为本地socket文件句柄 如果是说明第一次连接 if fileno == server.fileno(): #等待客户端连接 connection,addr=server.accept() #取客户端的socket句柄整形比如 1 15 212 connFd=connection.fileno() #设置客户端socket为非阻碍模式 connection.setblocking(0) #将客户端socket句柄注册到EPOLLIN epoll.register(connFd,select.EPOLLIN) #将客户端socket句柄整形 和 客户端socket句柄放到connections字典暂存 connections[connFd]=connection #判断客户端是否断开连接 elif event & select.EPOLLHUP: print('close') #销毁已断开的客户端socket句柄整形的哦 epoll.unregister(fileno) #关闭客户端socket连接 connections[fileno].close() #删除客户端暂存数据 del connections[fileno] #判断客户端是否为收 elif event & select.EPOLLIN: #接受数据 并strip掉没用的 比如:空格 requests[fileno]=connections[fileno].recv(1024).strip() #将客户端文件句柄整形的 从EPOLLIN中转移到 EPOLLOUT epoll.modify(fileno,select.EPOLLOUT) #判断客户端是否为发 elif event & select.EPOLLOUT: #发送数据 connections[fileno].send(requests[fileno]) #将客户端文件句柄整形的 从EPOLLOUT中转移到 EPOLLIN epoll.modify(fileno,select.EPOLLIN)
Epoll Client:
#!/usr/bin/env python #-*- coding:utf-8 -*- #auther = Alan import socket client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) host_address = ('192.168.17.128',1234) client_socket.connect(host_address) #client_socket.setblocking(0) while True: data = raw_input('please input:') client_socket.sendall(data) server_data = client_socket.recv(1024) print server_data client_socket.close()