使用协程的纯python异步i/o

bluelet的Python项目详细描述


"echo"服务器

"echo"服务器是演示socket编程的典型愚蠢示例。它只需接受连接、读取行并将读取的所有内容写回客户端即可。

下面是一个使用普通python套接字的示例:

import socket
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener.bind(('', 4915))
listener.listen(1)
while True:
    sock, addr = listener.accept()
    while True:
        data = sock.recv(1024)
        if not data:
            break
        sock.sendall(data)

代码非常简单,但它的同步性有一个主要问题:服务器一次只能接受一个连接。即使对于非常小的服务器应用程序,这也做不到。

解决此问题的一种方法是分叉多个运行相同同步代码的操作系统线程或进程。然而,这很快变得复杂,使应用程序更难管理。python的asyncore模块提供了一种编写异步服务器的方法,这些服务器在同一个os线程中接受多个连接:

import asyncore
import socket
class Echoer(asyncore.dispatcher_with_send):
    def handle_read(self):
        data = self.recv(1024)
        self.send(data)
class EchoServer(asyncore.dispatcher):
    def __init__(self):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind(('', 4915))
        self.listen(1)
    def handle_accept(self):
        sock, addr = self.accept()
        handler = Echoer(sock)
server = EchoServer()
asyncore.loop()

异步I/O允许线程运行一个 select() 循环来处理所有连接,并在事件(如接受和数据包)发生时发送 回调。然而,代码变得更加复杂:一个简单的echo服务器的执行被分解成更小的方法,控制流变得难以遵循。

bluelet(与其他基于coroutine的异步i/o库一样)允许您编写看起来是连续的但实际上是并发的代码。像这样:

import bluelet
def echoer(conn):
    while True:
        data = yield conn.recv(1024)
        if not data:
            break
        yield conn.sendall(data)
bluelet.run(bluelet.server('', 4915, echoer))

除了 yield 关键字外,请注意,此代码与我们的第一个顺序版本非常相似。(bluelet还负责样板套接字设置代码。)这是有效的,因为 echore 是一个python协同程序:只要它说 yield ,它就会暂时中止它的执行。然后,bluelet的调度器接管并等待事件,就像asyncore一样。当套接字事件发生时,协程将在它产生的点处恢复。所以不需要分解代码;它们都可以显示为单个代码块。整洁!

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
由于测试失败,java testcontainers maven构建失败   java实现jacobi算法实现laplace方程   java中的多线程:如何在不等待所有线程使用ExecutorService完成任务的情况下终止所有线程的执行?   java Hello World不在Android Studio 3中工作   ubuntu Tomcat7的Java版本不正确   java Javafx内存泄漏   对于手动实现的Spring数据存储库方法,我应该使用Java8默认方法吗?   googleappengine中的java添加过滤查询   html当使用JSOUP库在Java中读取标签时,如何保留标签(如<br>、<ul>、<li>、<p>等)的含义?   编码为什么jasper生成的报告在Java中不显示西里尔语(保加利亚语)?   java有没有办法隐藏当前位置和jdk动作?   java找出编译原型文件的版本   有没有办法在运行时更改java方法的访问修饰符?   语法字符串。。。Java中的参数   java数组元素在添加其他元素时会相互覆盖   eclipse中的java GWT项目   java如何为spring rest模板请求将动态json属性名映射到jackson   java无法在Windows 10上找到特定的JDK   在xml字符串和java字符串之间提取正则表达式子字符串