asynchat —异步套接字命令/响应处理程序

源代码: Lib/asynchat.py

自 3.6 版起已弃用:请改用asyncio


Note

存在此模块仅是为了向后兼容。对于新代码,我们建议使用asyncio

此模块构建在asyncore基础结构的基础上,简化了异步 Client 端和服务器,并使处理其元素以任意字符串终止或长度可变的协议变得更加容易。 asynchat定义了子类的抽象类async_chat,提供了collect_incoming_data()found_terminator()方法的实现。它使用与asyncore相同的异步循环,并且两种类型的通道asyncore.dispatcherasynchat.async_chat可以在通道图中自由混合。通常,asyncore.dispatcher服务器通道在接收到传入的连接请求时会生成新的asynchat.async_chat通道对象。

asyncore.dispatcher一样,async_chat定义了一组事件,这些事件是pass对select()调用后的套接字条件的分析生成的。一旦轮询循环开始,事件处理框架将调用async_chat对象的方法,而程序员无需采取任何措施。

可以修改两个类的属性,以提高性能,甚至可能节省内存。

asyncore.dispatcher不同,async_chat允许您定义* producer 的 FIFO 队列。生产者仅需要一种方法more(),该方法应返回要在通道上传输的数据。生产者pass使其more()方法返回空字节对象来指示耗尽(即,它不包含更多数据)。此时,async_chat对象将生产者从队列中删除,并开始使用下一个生产者(如果有)。当生产者队列为空时,handle_write()方法不执行任何操作。您使用通道对象的set_terminator()方法来描述如何识别来自远程端点的传入传输的结尾或其中的重要断点。

要构建Function正常的async_chat子类,您的 Importing 法collect_incoming_data()found_terminator()必须处理通道异步接收的数据。方法如下所述。

term Description
string 在 Importing 流中找到字符串时将调用found_terminator()
integer 收到指定数量的字符后将呼叫found_terminator()
None Channel 将永远永远收集数据

请注意,调用found_terminator()之后,终止符之后的任何数据将可供通道读取。

asynchat Example

以下部分示例显示了如何使用async_chat读取 HTTP 请求。 Web 服务器可能会为每个传入的 Client 端连接创建http_request_handler对象。请注意,最初将通道终止符设置为与 HTTPHeaders 末尾的空白行匹配,并且有一个标志指示正在读取 Headers。

读取 Headers 后,如果请求的类型为 POST(指示 Importing 流中存在其他数据),则Content-Length:Headers 用于设置数字终止符,以从通道中读取正确数量的数据。

将通道终止符设置为None之后,一旦将所有相关 Importing 整理完毕,就会调用handle_request()方法,以确保忽略 WebClient 端发送的任何无关数据。

import asynchat

class http_request_handler(asynchat.async_chat):

    def __init__(self, sock, addr, sessions, log):
        asynchat.async_chat.__init__(self, sock=sock)
        self.addr = addr
        self.sessions = sessions
        self.ibuffer = []
        self.obuffer = b""
        self.set_terminator(b"\r\n\r\n")
        self.reading_headers = True
        self.handling = False
        self.cgi_data = None
        self.log = log

    def collect_incoming_data(self, data):
        """Buffer the data"""
        self.ibuffer.append(data)

    def found_terminator(self):
        if self.reading_headers:
            self.reading_headers = False
            self.parse_headers(b"".join(self.ibuffer))
            self.ibuffer = []
            if self.op.upper() == b"POST":
                clen = self.headers.getheader("content-length")
                self.set_terminator(int(clen))
            else:
                self.handling = True
                self.set_terminator(None)
                self.handle_request()
        elif not self.handling:
            self.set_terminator(None)  # browsers sometimes over-send
            self.cgi_data = parse(self.headers, b"".join(self.ibuffer))
            self.handling = True
            self.ibuffer = []
            self.handle_request()
首页