asyncio协议
服务端
import asyncio
import logging
import sys
from typing import Optional
SERVER_ADDRESS = ('localhost', 10000)
logging.basicConfig(
level=logging.DEBUG,
format='%(name)s: %(message)s',
stream=sys.stderr,
)
log = logging.getLogger('main')
class EchoServer(asyncio.Protocol):
"""
每个新客户端连接都会触发对connection_made()的调用。
transport参数是asyncio.Transport的一个实例,它提供了使用套接字进行异步I/O的抽象。
不同类型的通信提供不同的传输实现,所有这些都具有相同的API。
例如,有单独的传输类用于处理套接字和处理管道到子进程。
传入客户端的地址可通过get_extra_info()传输获得,
get_extra_info()是一种特定于实现的方法。
启动顺序
State machine of calls:
start -> CM [-> DR*] [-> ER?] -> CL -> end
* CM: connection_made()
* DR: data_received()
* ER: eof_received()
* CL: connection_lost()
"""
def connection_made(self, transport):
self.transport = transport
self.address = transport.get_extra_info('peername')
self.log = logging.getLogger('EchoServer_{}_{}'.format(*self.address))
self.log.debug('connection accepted')
def data_received(self, data: bytes) -> None:
"""
类似于一个循环,循环调用这个方法读取内容。
"""
self.log.debug('received{!r}'.format(data))
self.transport.write(data)
self.log.debug('sent {!r}'.format(data))
def eof_received(self) -> Optional[bool]:
"""
有些传输支持特殊的文件结束指示符(“EOF”)。
遇到EOF时,调用eof_received()方法。在这个实现中,
EOF被发送回客户端以指示它被接收到。
因为不是所有的传输都支持显式的EOF,
所以该协议首先询问传输发送EOF是否安全。
:return:
"""
self.log.debug('received EOF')
if self.transport.can_write_eof():
self.transport.write_eof()
def connection_lost(self, exc: Optional[Exception]) -> None:
"""
当连接关闭时,无论是正常情况还是由于错误,
都会调用协议的connection_lost()方法。
如果有错误,参数包含适当的异常对象。否则就没有了。
:param exc:
:return:
"""
if exc:
self.log.error('ERROR:{}'.format(exc))
else:
self.log.debug('closing')
super().connection_lost(exc)
if __name__ == '__main__':
"""
然后需要运行事件循环以处理事件和处理客户端请求。
对于长时间运行的服务,run_forever()方法是执行此操作的最简单方法。
当事件循环被应用程序代码或通过发送进程信号停止时,
可以关闭服务器以正确清理套接字,
然后可以关闭事件循环以在程序退出之前完成处理任何其他协同程序。
"""
loop = asyncio.get_event_loop()
factory = loop.create_server(EchoServer, *SERVER_ADDRESS)
server = loop.run_until_complete(factory)
log.debug('starting up on {} port {}'.format(*SERVER_ADDRESS))
try:
loop.run_forever()
finally:
log.debug('closing server')
server.close()
loop.run_until_complete(server.wait_closed())
log.debug('closing event loop')
loop.close()
客户端
import asyncio
import functools
import logging
import sys
from asyncio import transports
from typing import Optional
MESSAGES = [
b'This is the message. ',
b'It will be sent ',
b'in parts.',
]
SERVER_ADDRESS = ('localhost', 10000)
logging.basicConfig(
level=logging.DEBUG,
format='%(name)s: %(message)s',
stream=sys.stderr,
)
log = logging.getLogger('main')
event_loop = asyncio.get_event_loop()
class EchoClient(asyncio.Protocol):
"""
客户机协议类定义了与服务器相同的方法,但实现不同。
类构造函数接受两个参数,一个是要发送的消息列表,
另一个是将来要使用的实例,通过接收来自服务器
的响应来表示客户机已经完成了一个工作周期。
"""
def __init__(self, messages, future):
super().__init__()
self.messages = messages
self.log = logging.getLogger('EchoClient')
self.f = future
def connection_made(self, transport: transports.BaseTransport) -> None:
self.transport = transport
self.address = transport.get_extra_info('peername')
self.log.debug('connecting to {} port {}'.format(*self.address))
for msg in self.messages:
transport.write(msg)
self.log.debug('sending {!r}'.format(msg))
if transport.can_write_eof():
transport.write_eof()
def data_received(self, data: bytes) -> None:
self.log.debug("received {!r}".format(data))
def eof_received(self) -> Optional[bool]:
self.log.debug('received EOF')
self.transport.close()
if not self.f.done():
self.f.set_result(True)
def connection_lost(self, exc: Optional[Exception]) -> None:
self.log.debug('server closed connection')
self.transport.close()
if not self.f.done():
self.f.set_result()
super().connection_lost(exc)
client_completed = asyncio.Future()
client_factory = functools.partial(
EchoClient,
messages=MESSAGES,
future=client_completed,
)
factory_coroutine = event_loop.create_connection(
client_factory,
*SERVER_ADDRESS,
)
log.debug('waiting for client to complete')
try:
event_loop.run_until_complete(factory_coroutine)
event_loop.run_until_complete(client_completed)
finally:
log.debug('closing event loop')
event_loop.close()
asyncio协议的更多相关文章
- asyncio
一.简介 asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持. asyncio的编程模型就是一个消息循环.我们从asyncio模块中直接获取一个EventLoop的引用, ...
- 使用asyncio实现redis客户端
redis协议格式请参考,http://doc.redisfans.com/topic/protocol.html 这里简单介绍下: *<参数数量> \r\n $<参数 的字节数量& ...
- asyncio异步IO——Streams详解
前言 本文翻译自python3.7官方文档--asyncio-stream,译者马鸣谦,邮箱 1612557569@qq.com.转载请注明出处. 数据流(Streams) 数据流(Streams)是 ...
- 我实在不懂Python的Asyncio
原语 事件循环(Event Loop) Awaitables和Coroutines Coroutine Wrappers Awaitables and Futures Tasks Handles Ex ...
- 爬虫高性能 asyncio库 twisted库 tornado库
一 背景知识 爬虫的本质就是一个socket客户端与服务端的通信过程,如果我们有多个url待爬取,只用一个线程且采用串行的方式执行,那只能等待爬取一个结束后才能继续下一个,效率会非常低. 需要强调的是 ...
- python之asyncio
asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持. asnycio是用来编写并发代码的库,python3.5以后使用async/await语法. asyncio 被用作 ...
- (转)asyncio --- 异步 I/O
原文:https://docs.python.org/zh-cn/3/library/asyncio.html asyncio 是用来编写 并发 代码的库,使用 async/await 语法. asy ...
- asyncio并发编程
一. 事件循环 1.注: 实现搭配:事件循环+回调(驱动生成器[协程])+epoll(IO多路复用),asyncio是Python用于解决异步编程的一整套解决方案: 基于asynico:tornado ...
- Python开发【异步】:asyncio
异步asyncio asyncio是一个使用async / await语法编写并发代码的库. asyncio用作多个Python异步框架的基础,这些框架提供高性能的网络和Web服务器,数据库连接库,分 ...
随机推荐
- jeecg字典表-系统字典
新建字典 录入字典信息 添加类型 录入完类型后效果 新建列表用户 保存 同步数据库 同步完之后,对应的数据库中会创建对应的表. 测试表功能 保存之后,数据库保存对应的字段 生成代码 刷新工程之后,生成 ...
- Minieye杯第十五届华中科技大学程序设计邀请赛网络赛D Grid(简单构造)
链接:https://ac.nowcoder.com/acm/contest/560/D来源:牛客网 题目描述 Give you a rectangular gird which is h cells ...
- HTML之表格
表格标签和表格标题 表格标签 <table> <tr> <td></td> ...... </tr> <tr> <td&g ...
- 证明与计算(4): 完美散列函数(Perfect Hash function)
原文:wiki: 完美散列函数 假设,写一个SQL语句解析器,词法分析对SQL语句解析,把语句分成了多个token,一般这个时候会需要查询这个token是否是一个关键字token. 例如keyword ...
- Linux C/C++ 链接选项之静态库--whole-archive,--no-whole-archive和--start-group, --end-group
参照这两篇博客: http://stackoverflow.com/questions/805555/ld-linker-question-the-whole-archive-option http: ...
- ZabbixServer安装
Zabbix服务端安装主要分二种一直yum在线安装,一种离线安装,在线安装只需简单命令自己便可安装离线安装得自定义路径等等...比较繁琐不过便于文件管理.这里简单配置一下在线安装. https://w ...
- ubuntu only enable left click
xmodmap -e "pointer = 1 0 0 0 0 0 0 0 0 0"
- kubernetes 将pod运行在某些特定的节点上,给节点打标签
给节点打上标签: kubectl label node <node_name> GPU=true #打上标签 GPU=true 在创建pod的yaml文件时: 添加 nodeSel ...
- 【SPOJ】DIVCNTK min_25筛
题目大意 给你 \(n,k\),求 \[ S_k(n)=\sum_{i=1}^n\sigma_0(i^k) \] 对 \(2^{64}\) 取模. 题解 一个min_25筛模板题. 令 \(f(n)= ...
- 13-jQuery的ajax
什么是ajax AJAX = 异步的javascript和XML(Asynchronous Javascript and XML) 简言之,在不重载整个网页的情况下,AJAX通过后台加载数据,并在网页 ...