python iocp_【tulip】 - IOCP
为了让I/O阻塞的时候,程序还可以去干别的。除了使用线程模型,让操作系统的内核去调度多个线程,Windows提供了IOCP机制。简单来说就是一个操作系统提供的回调机制。分成四个步骤
生成key,并建立映射关系:向操作系统创建一个key,程序内部把这个key和一个回调函数对应起来
调用:执行阻塞的I/O操作,并指定key来对应这个I/O操作
轮询,返回key:程序轮询操作系统询问是否有新的I/O操作完成,如果有完成的会返回对应的key
用key查找,并回调:因为创建key的时候内部已经和一个回调函数对应起来了,所以这个时候之前映射好的函数会被回调
前面的例子太复杂了,我们把accept后面的操作全部忽略掉。单独看一个服务器接收客户端连接的代码:
import socket
from asyncio import _overlapped
import struct
listen_sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=socket.IPPROTO_IP)
listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen_sock.bind(('0.0.0.0', 9090))
listen_sock.listen(0)
NULL = 0
concurrency=0xffffffff
_iocp = _overlapped.CreateIoCompletionPort(_overlapped.INVALID_HANDLE_VALUE, NULL, 0, concurrency)
_overlapped.CreateIoCompletionPort(listen_sock.fileno(), _iocp, 0, 0)
conn_sock = socket.socket(listen_sock.family)
conn_sock.settimeout(0)
ov = _overlapped.Overlapped(NULL)
ov.AcceptEx(listen_sock.fileno(), conn_sock.fileno())
def on_accepted():
buf = struct.pack('@P', listen_sock.fileno())
conn_sock.setsockopt(socket.SOL_SOCKET, _overlapped.SO_UPDATE_ACCEPT_CONTEXT, buf)
conn_sock.settimeout(listen_sock.gettimeout())
print('connected from %s:%s' % conn_sock.getpeername())
return conn_sock, conn_sock.getpeername()
callback_map = {}
if ov.pending:
callback_map[ov.address] = on_accepted
else:
on_accepted()
while True:
# wait maximum 1 second
status = _overlapped.GetQueuedCompletionStatus(_iocp, 1000)
if status is None:
continue # try again
err, transferred, key, address = status
callback = callback_map[address]
callback()
break
这段代码使用了Python 3.4。其中 _overlapped.Overlapped(NULL) 这一步是创建key,ov.AcceptEx(listen_sock.fileno(), conn_sock.fileno()) 是做一个I/O调用,后面的 _overlapped.GetQueuedCompletionStatus(_iocp, 1000) 是轮询,callback_map[address] 这一步是根据返回的key查找对应的回调函数回调。
这种实现方式与前面基于线程的方式显著不同:
程序内状态的上下文的保存不再由操作系统负责,而是通过callback_map由程序代码自己来负责的
操作系统只负责维护阻塞I/O操作与对应的key(也就是overlapped.address这个东西)的关系。程序内的多个并发流程(本例子里只有一个客户端)需要由程序自身通过key和callback_map来自己做调度。
这样状态从多个线程的多个栈上,变成了只有一个线程,但是在线程内部有一个callback_map来维护单线程内多个并发流程的状态。某种程度上来说,相对于多线程是把一些操作系统的上下文保存和调度职责从操作系统内核移到了网络程序里。
python iocp_【tulip】 - IOCP相关推荐
- [4]Python数据类型【1】
本文会很长,包含了很多函数,请认真阅读. 我会尽量以最精简的方式向您介绍.(包含上次我剩下的input函数转换类型方法) 目录 1.str类型(全称string字符串)与str()函数 1-str类型 ...
- Python正则表达式【转】
Python正则表达式[转] 原文:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html
- python实现【冒泡排序】(bubbleSort)
python实现[冒泡排序](bubbleSort) 算法原理介绍 冒泡排序是一种简单的排序算法.它的基本原理思想是重复地走访过要排序的数列,并且依次比较两个元素,如果它们的顺序错误就把它们的位置进行 ...
- Python图像处理【2】探索Python图像处理库
探索Python图像处理库 0. 前言 1. 利用 scikit-image 绘制图像 2. 使用 SciPy 模块裁剪/调整图像大小 3. 使用 OpenCV 绘制轮廓 3.1 轮廓简介 3.2 绘 ...
- Python图像处理【1】图像与视频处理基础
图像与视频处理基础 0. 前言 1. 在 3D 空间中显示 RGB 图像颜色通道 1.1 图像表示 1.2 在 3D 空间中绘制颜色通道 2. 使用 scikit-video 读/写视频文件 2.1 ...
- python设计模式【8】-模型·视图·控制器-复合模式
UML类图简介 设计模式的分类 面向对象的设计原则 python设计模式[1]-单例模式 python设计模式[2]-工厂模式 python设计模式[3]-门面模式 python设计模式[4]-代理模 ...
- python直方图【色卡】
python直方图[色卡] 直方图code 结果 色卡 直方图code import matplotlib.pyplot as plt import os # 文件保存所需头文件 # 横坐标 x = ...
- Python爬虫【二】爬取PC网页版“微博辟谣”账号内容(selenium同步单线程)
专题系列导引 爬虫课题描述可见: Python爬虫[零]课题介绍 – 对"微博辟谣"账号的历史微博进行数据采集 课题解决方法: 微博移动版爬虫 Python爬虫[一]爬取移 ...
- Python爬虫【四】爬取PC网页版“微博辟谣”账号内容(selenium多线程异步处理多页面)
专题系列导引 爬虫课题描述可见: Python爬虫[零]课题介绍 – 对"微博辟谣"账号的历史微博进行数据采集 课题解决方法: 微博移动版爬虫 Python爬虫[一]爬取移 ...
最新文章
- eclipse中配置tomcat之后指定项目部署的目录
- SpringBoot非官方教程 | 第二篇:Spring Boot配置文件详解
- C++类模板的三种特化类型
- iou画 yolov3_专栏 | 【从零开始学习YOLOv3】4. YOLOv3中的参数进化
- 学java交学费包分配_java 学生缴学费案例:
- 罗斯蒙特电磁流量计8723说明书_罗斯蒙特8732E电磁流量计对环境和温度的限制
- C语言链表存储数据并排序,c语言求助:怎么根据链表中的某个数据对链表进行排序?...
- js 闭包作用(转自别人的)
- 华为机试HJ46:截取字符串
- 2019.01.01洛谷 P4725/P4726 多项式对数/指数函数(牛顿迭代)
- php 银行支付通道_基于PHP框架的聚合四方支付系统
- java 蓝牙串口_java_android_0057 蓝牙串口助手源码
- windows自带桌面远程控制
- sklearn.metrics confusion_matrix注意事项
- Vue前端项目-系统监控-数据监控
- 最新Java后端面经合集 | 阿里腾讯百度字节
- 取消计算机系统密钥,BitLocker驱动器被加密怎么恢复密钥 忘了密码取消删除方法...
- 【C++】引用、内联函数、函数重载、函数默认参数(缺省参数)与占位参数、extern “C“ 浅析
- Serverless 可观测性的过去、现在与未来
- 主流币仍被摁在地上摩擦,平台币已扬起一场美丽的春梦