服务端异步IO配合协程浅析

代码如下

#coding:utf-8
import socket
from selectors import DefaultSelector, EVENT_READ, EVENT_WRITE
selector = DefaultSelector()stopped = Falseresponse = b'HTTP/1.0 200 OK\r\nDate: Mon, 1 Jan 1996 01:01:01 GMT\r\n'
response += b'Content-Type: text/plain\r\nContent-Length: 13\r\n'
response += b'hello world'class Future:def __init__(self):self.result = Noneself._callback = []def add_done_callback(self, fn):self._callback.append(fn)def set_result(self, result):self.result = resultfor fn in self._callback:fn(self)def __iter__(self):yield selfreturn self.resultclass Task:def __init__(self, coro):self.coro = corof = Future()f.set_result(None)self.step(f)def step(self, future):try:next_future = self.coro.send(future.result)print("next_future: ", next_future)except StopIteration as e:print("step stop :", e.value)returnnext_future.add_done_callback(self.step)class ConHandler(object):def __init__(self, con, addr):self.con = con                                      # 新连接实例self.addr = addr                                    # 新连接地址def _read_ready(self):f = Future()def sock_read():                                    # 由于没有解析相应的流协议,所以这里直接接受所有的数据,# 如果解析具体协议也可以改写成协程all_data = b""                                  # 接受数据while True:                                     # 一直接受数据直到数据接受完成try:data = self.con.recv(10)if data:print("recv data : ", data)all_data += dataelse:print("break while")breakexcept BlockingIOError:print("BlockingIOError")breakprint("all_data", all_data)# selector.unregister(self.con.fileno())f.set_result(None)                              # 当数据接受完成后,调用f实例的回调方法,进入将主流程往下执行一步selector.register(self.con.fileno(), EVENT_READ, sock_read)     # 注册连接的读事件并注册回调函数yield fselector.unregister(self.con.fileno())              # 取消连接的注册事件def fetch(self):# 读事件到来一次读完fu = yield from self._read_ready()                  # 调用读数据print("recv_data: ", fu)# handler  处理请求self.response = response*10000result = yield from self.sock_send_all()            # 将处理的数据发送出去print("send after : ", result)def sock_send_all(self):send_length = yield from self.sock_send()           # 发送相应数据,返回发送的数据长度self.response = self.response[send_length:]         # 减去已经发送的数据长度while send_length:                                  # 如果发送长度不为0send_length = yield from self.sock_send()       # 继续发送数据self.response = self.response[send_length:]     # 减去已经发送的数据长度returndef sock_send(self):f = Future()def _sock_send():con_length = self.con.send(self.response)f.set_result(con_length)selector.register(self.con.fileno(), EVENT_WRITE, _sock_send)send_length = yield fselector.unregister(self.con.fileno())return send_lengthdef create_server():sock = socket.socket()                                      # 创建连接sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 设置端口重用sock.bind(('0.0.0.0', 9003))                                # 设置监听连接端口sock.listen(10)                                             # 设置监听缓存区sock.setblocking(0)                                         # 设置连接非阻塞def sock_accept():                                          # 如果sock的新请求连接处理回调函数try:conn, addr = sock.accept()                          # 接受新请求conn.setblocking(False)                             # 设置接受新连接非阻塞print(conn)except Exception:passTask(ConHandler(conn, addr).fetch())                # 用任务类包裹处理流程,使之流程协程处理selector.register(sock.fileno(), EVENT_READ, sock_accept)   # 注册sock的连接读事件并设置读事件的回调函数def loop():while not stopped:events = selector.select()                              # 获取触发的事件for event_key, event_mask in events:callback = event_key.data                           # 获取触发事件的回调函数callback()                                          # 执行回调函数if __name__ == '__main__':create_server()loop()

基于上一篇的异步协程爬虫,现在服务端的大概原理是:
1.注册服务端连接的读事件和读回调函数,
2.读回调函数,将接受的新请求传入接受处理函数,并包装成Task类执行,
3.注册新连接的读事件,接受完成数据后,调用Task往下执行,
4.处理完成后,将处理的数据写出时,注册新连接的写事件,如果数据未写完继续执行,循环执行,直到数据写出完成
5.取消连接的事件监听
6.继续等待新连接的介入
至此上述代码的执行流程已完成。

服务端异步IO配合协程浅析相关推荐

  1. Python 异步 IO 、协程、asyncio、async/await、aiohttp

    From :廖雪峰 异步IO :https://www.liaoxuefeng.com/wiki/1016959663602400/1017959540289152 Python Async/Awai ...

  2. 异步IO(协程,消息循环队列)

    同步是CPU自己主动查看IO操作是否完成,异步是IO操作完成后发出信号通知CPU(CPU是被通知的) 阻塞与非阻塞的区别在于发起IO操作之后,CPU是等待IO操作完成再进行下一步操作,还是不等待去做其 ...

  3. 异步爬虫框架与协程浅析

    异步爬虫框架与协程浅析 经典原文使用协成完成异步爬虫原文链接 根据分享原文链接. Python基于协程的实现,其实是利用了Python生成器的特性完成的,Python生成器的原理其实涉及到用户态绿色线 ...

  4. 并发编程之进程池,线程池 和 异步回调,协程

    1.进程池和线程池 2.异步回调 3.协程 4.基于TCP使用多线程实现高并发 一.进程池和线程池 什么是进程池和线程池: ''' 池 Pool 指的是一个容器 线程池就是用来存储线程对象的 容器创建 ...

  5. 关于C10K、异步回调、协程、同步阻塞

    2019独角兽企业重金招聘Python工程师标准>>> 最近到处在争论这些话题,发现很多人对一些基础的常识并不了解,在此发表一文做一下解释.此文未必能解答所有问题,各位能有一个大致的 ...

  6. Python|线程和进程|阻塞|非阻塞|同步|异步|生成器和协程|资源竞争|进程间通信|aiohttp库|daemon属性值详解|语言基础50课:学习(11)

    文章目录 系列目录 原项目地址 第34课:Python中的并发编程-1 线程和进程 多线程编程 使用 Thread 类创建线程对象 继承 Thread 类自定义线程 使用线程池 守护线程 资源竞争 G ...

  7. 【Kotlin 协程】协程简介 ( 协程概念 | 协程作用 | 创建 Android 工程并进行协程相关配置开发 | 异步任务与协程对比 )

    文章目录 一.协程概念 二.协程作用 三.创建 Android 工程并进行协程相关配置 1.创建 Android 工程 2.配置协程环境 3.布局文件 4.异步任务代码示例 5.协程代码示例 6.完整 ...

  8. python 异步编程:协程与 asyncio

    文章目录 一.协程(coroutine) 1.1 协程的概念 1.2 实现协程的方式 二.asyncio 异步编程 2.1 事件循环 2.2 快速上手 2.3 运行协程 2.4 await 关键字 2 ...

  9. python3异步编程_协程 Python异步编程(asyncio)

    协程(Coroutine) 也可以被称为微线程,是一种用户态内的上下文切换技术.简而言之,其实就是通过一个线程实现代码块相互切换执行. 直接上代码,例如: 同步编程 import time def f ...

最新文章

  1. pytest文档3-pycharm运行pytest
  2. 苹果台式电脑怎么开机_龙华苹果电脑回收公司,台式电脑回收公司电话
  3. 27. 二叉搜索树与双向链表(C++版本)
  4. 远程连接线上的mysql失败 客户端和代码连接
  5. latex 数学符号
  6. Adobe Flash Player历史版本下载
  7. 并行处理提高工作效率
  8. 电子嵌入式硬件软件培训
  9. python控制蓝牙pybluez_Python之蓝牙通讯模块pybluez学习笔记
  10. htts 及 tomcat ssl配置
  11. 微信小程序的图形验证码实现
  12. bootstrap侧面菜单栏
  13. dlink 备份文件_dlink交换机如何保存数据
  14. 易语言 上传文件到远程服务器,易语言与向远程服务器发送文件夹
  15. matlab里motor的符号,motor的用法总结大全
  16. CRM适用于什么企业?
  17. 微信关注即可使用 Wi-Fi,取消关注即断网的路由器实现的流程原理以及步骤
  18. 协同过滤算法概述与python 实现协同过滤算法基于内容(usr-item,item-item)
  19. 故宫文创产品一年卖出15亿元
  20. linux看磁盘是sas还是sata吗,SAS硬盘和SATA硬盘它们有何不同,硬盘都有哪些类型...

热门文章

  1. 一口一个,超灵活的Python迷你项目
  2. @所有技术社区,年度”社区之星“开选,快来盘点各家技术大佬
  3. 量子计算与AI“双拳”出击,他们锁定38种潜在抗疫药物
  4. TF 2.1.0-rc2发布,2020年停止支持Python 2
  5. 银行卡大小的充电宝,买就送耳机!
  6. AI时代,中国技术创新如何弯道超车?
  7. 一文讲清楚什么是迁移学习?以及它都用在哪些深度学习场景?
  8. 卧槽!成就了Java,开发框架排第一,你还是不够了解它!
  9. 我终于决定要放弃 okhttp、httpClient,选择了这个牛逼的神仙工具!贼爽
  10. 十年后,这款优秀的工具终于给出了不开源的原因