**原理图**
![](https://box.kancloud.cn/eadb7b169483f83c311e68102b2b8cc3_655x215.png)
1. Create an epoll object——创建1个epoll对象
2. Tell the epoll object to monitor specific events on specific sockets——告诉epoll对象,在指定的socket上监听指定的事件
3. Ask the epoll object which sockets may have had the specified event since the last query——询问epoll对象,从上次查询以来,哪些socket发生了哪些指定的事件
4. Perform some action on those sockets——在这些socket上执行一些操作
5. Tell the epoll object to modify the list of sockets and/or events to monitor——告诉epoll对象,修改socket列表和(或)事件,并监控
6. Repeat steps 3 through 5 until finished——重复步骤3-5,直到完成
7. Destroy the epoll object——销毁epoll对象
**相关用法**
~~~
import select 导入select模块
epoll = select.epoll() 创建一个epoll对象
epoll.register(文件句柄,事件类型) 注册要监控的文件句柄和事件
事件类型:
select.EPOLLIN 可读事件
select.EPOLLOUT 可写事件
select.EPOLLERR 错误事件
select.EPOLLHUP 客户端断开事件
epoll.unregister(文件句柄) 销毁文件句柄
epoll.poll(timeout) 当文件句柄发生变化,则会以列表的形式主动报告给用户进程,timeout
为超时时间,默认为-1,即一直等待直到文件句柄发生变化,如果指定为1
那么epoll每1秒汇报一次当前文件句柄的变化情况,如果无变化则返回空
epoll.fileno() 返回epoll的控制文件描述符(Return the epoll control file descriptor)
epoll.modfiy(fineno,event) fineno为文件描述符 event为事件类型 作用是修改文件描述符所对应的事件
epoll.fromfd(fileno) 从1个指定的文件描述符创建1个epoll对象
epoll.close() 关闭epoll对象的控制文件描述符
~~~
注:EPOLLIN(可读),EPOLLOUT(可写)
* EPOLLET: 边缘触发模式(只通知一次)
* EPOLLLT:水平触发模式(通知后没有做处理的话还会继续通知)
~~~
import socket
import select
tcp_server_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcp_server_tcp.bind(('0.0.0.0', 9292))
tcp_server_tcp.listen(128)
# 设置套接字为非阻塞方式
tcp_server_tcp.setblocking(False)
# 创建一个epoll对象
epl = select.epoll()
# 将监听套接字对应的fd注册到epoll中
epl.register(tcp_server_tcp.fileno(), select.EPOLLIN)
# fd为key,socket为value
fd_event_dict = dict()
while True:
# 默认阻塞,直到os监测到数据到来,通过事件通知的方式,此时才会解开阻塞
# epl.poll(10) 里面可以写超时时间
fd_event_list = epl.poll() # 结果是这样,[(fd, event), (套接字对应的文件描述符,这个文件描述符到底是什么事件,例如,可以调用recv接收等)]
if not fd_event_list:
print("epoll超时无活动连接,重新轮询......")
continue
print("有", len(fd_event_list), "个新事件,开始处理......")
for fd, event in fd_event_list:
# 如果活动socket为当前服务器socket,表示有新连接
if fd == tcp_server_tcp.fileno():
# 等待新客户端的链接
new_socket, client_addr = tcp_server_tcp.accept()
# 注册新连接fd到待读事件集合
epl.register(new_socket.fileno(), select.EPOLLIN)
# 把新连接的文件句柄以及对象保存到字典
fd_event_dict[new_socket.fileno()] = new_socket
elif event == select.EPOLLIN:
# 判断已经链接的客户端是否有数据发送过来
recv__data = fd_event_dict[fd].recv(1024).decode('utf-8', 'ignore')
if recv__data:
print('收到的数据是: ', recv__data)
# 发送数据回去
fd_event_dict[fd].send(recv__data.encode('utf-8'))
else:
fd_event_dict[fd].close()
epl.unregister(fd)
del fd_event_dict [fd]
~~~
- python入门
- 软件安装
- anaconda使用
- py解释器
- 数据类型和变量
- 编码
- 字符串
- 格式化
- 数据类型
- 运算符
- list和tuple
- 列表生成式
- dict和set
- 切片和迭代
- set,list,tuple之间互换
- is和==
- 公共方法
- 反射操作
- 数学运算
- 类型转换
- 对象操作
- 序列操作
- 运算符
- 内置函数
- 交互操作
- 编译执行
- 引用
- 判断,循环
- 生成器
- 迭代器
- 函数
- 数据类型转换
- 空函数
- 参数
- 全局变量
- 返回值
- 递归
- 匿名函数
- 文件操作
- 打开和关闭
- 读写
- 备份文件
- 文件定位读写
- 重命名,删除
- 文件夹相关操作
- with
- StringIO和BytesIO
- 操作文件和目录
- 序列化
- 文件属性
- 面向对象
- 类和对象
- init()方法
- 魔法方法
- 继承
- 重写
- 多态
- 类属性,实例属性
- 静态方法和类方法
- 工厂模式
- 单例模式
- 异常
- 私有化
- 获取对象信息
- *args和**kwargs
- property属性
- 元类
- slots
- 定制类
- 枚举
- 模块
- 模块介绍
- 模块中的__name__
- 模块中的__all__
- 包
- 模块发布
- 模块的安装和使用
- 多模块开发
- 标准库
- 给程序传参数
- 时间
- 正则表达式
- GIL
- 深拷贝和浅拷贝
- 单元测试
- pyqt
- 安装
- 设置窗口图标和移动窗口
- 设置气泡提示和文本
- 图片展示
- 文本框控件
- 按钮控件
- 信号和槽
- 布局
- 对话框控件
- pygame
- 窗体关闭事件
- 显示图片
- 移动图片
- 文本显示
- 背景音和音效
- FPS计算
- surface
- 鼠标事件
- 函数式编程
- map/reduce
- filter
- sorted
- 返回函数
- 装饰器
- 偏函数
- 网络编程
- tcp
- udp
- socket
- epoll
- WSGI
- 多任务
- 多线程
- 多进程
- 分布式进程
- 协程
- 迭代器
- 生成器
- yield多任务
- greenlet
- gevent
- ThreadLocal
- asyncio
- async/await
- aiohttp
- 常用内建模块
- datetime
- collections
- base64
- struct
- hashlib
- hmac
- itertools
- urllib
- xml
- HTMLParser
- 常用第三方模块
- pillow
- requests
- chardet
- psutil
- 图形界面
- 海龟绘图
- Django
- 虚拟环境搭建
- ORM
- 模型类设计和表生成
- 模型类操作
- 关系查询
- 后台管理
- 配置mysql
- 字段属性和选项
- 查询
- 模型关联
- 路由
- 模板
- selenium
- 基本原理
- api
- 八种定位方式
- 元素的操作
- 多标签
- 多表单
- 鼠标,键盘
- 警告框
- 下拉框
- 执行js
- 等待
- cookie
- 封装
- unittest模块
- 断言
- 测试用例
- jmeter
- jmeter简介
- jmeter提取json
- 添加header和cookie
- 读取csv/txt文件
- 配置文件
- ant