首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

asynchat

源代码: Lib / asynchat.py

该模块建立在asyncore基础架构之上,简化了异步客户端和服务器,并且更容易处理元素被任意字符串终止或者长度可变的协议。asynchat定义async_chat你的子类的抽象类,提供collect_incoming_data()found_terminator()方法的实现。它使用相同的异步环路asyncore,和两种类型的信道的,asyncore.dispatcher并且asynchat.async_chat,可以自由地在信道映射进行混合。通常,asyncore.dispatcher服务器通道asynchat.async_chat会在接收传入连接请求时生成新的通道对象。

class asynchat.async_chat

这个类是一个抽象的子类asyncore.dispatcher。为了使实际使用中你必须继承的代码async_chat,提供有意义collect_incoming_data()found_terminator()方法。asyncore.dispatcher可以使用这些方法,尽管在消息/响应上下文中并不都是有意义的。

asyncore.dispatcherasync_chat定义了一组事件,这些事件是在select()调用之后通过分析套接字条件生成的。一旦轮询循环开始,async_chat对象的方法就由事件处理框架调用,而程序员不需要采取任何行动。

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

ac_in_buffer_size

异步输入缓冲区大小(默认4096)。

ac_out_buffer_size

异步输出缓冲区大小(默认4096)。

与之不同的是asyncore.dispatcherasync_chat您可以定义生产者的先入先出队列(fifo)。制作人只需要一种方法,more()它应该返回要在频道上传输的数据。生产者通过使其方法返回空字符串来指示耗尽(它不包含更多数据)more()。此时该async_chat对象从fifo中移除生产者并开始使用下一个生产者(如果有的话)。当生产者FIFO为空时,该handle_write()方法什么都不做。您使用通道对象的set_terminator()方法来描述如何识别来自远程端点的传入传输的末端或重要断点。

要建立一个正常运作的async_chat子类你的输入法collect_incoming_data()found_terminator()必须处理通道异步接收数据。方法如下所述。

async_chat.close_when_done()

推动None制片人fifo。当这个制作者从fifo中弹出时,它会导致频道关闭。

async_chat.collect_incoming_data(data)

调用数据保存任意数量的接收数据。必须重写的默认方法会引发NotImplementedError异常。

async_chat.discard_buffers()

在紧急情况下,此方法将丢弃输入和/或输出缓冲区以及生产者FIFO中保存的任何数据。

async_chat.found_terminator()

当传入的数据流符合由设置的终止条件时调用set_terminator()。必须重写的默认方法会引发NotImplementedError异常。缓冲的输入数据应该通过实例属性可用。

async_chat.get_terminator()

返回该通道的当前终止符。

async_chat.push(data)

将数据推送到频道的fifo以确保其传输。这就是让通道将数据写入网络所需要做的一切,尽管例如可以使用自己的生产者以更复杂的方式实现加密和分块。

async_chat.push_with_producer(producer)

拍摄一个制作者对象并将其添加到与该频道关联的制作者fifo中。当所有当前推送的生产者都用尽时,通道将通过调用其生产者的more()方法并将数据发送到远程端点来消费该生产者的数据。

async_chat.set_terminator(term)

设置要在通道上识别的终止条件。term可以是三种类型的值中的任何一种,对应于处理输入协议数据的三种不同方式。

术语

描述

当在输入流中找到字符串时,将调用found_terminator()

整数

当收到指定的字符数时,将调用found_terminator()

没有

该频道将继续永久收集数据

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

1. asynchat - 辅助类

class asynchat.fifo([list=None])

fifo已经由应用程序推送但尚未弹出用于写入到信道保持的数据。A fifo是一个列表,用于保存数据和/或生产者,直到他们需要。如果提供了list参数,那么它应该包含要写入通道的生产者或数据项。

is_empty()

当且仅当fifo为空时返回True

first()

返回push()fifo中最近编辑的项目。

push(data)

将给定的数据(可能是字符串或生产者对象)添加到生产者FIFO中。

pop()

如果fifo不为空,则返回True, first(),删除弹出的项目。返回False, None一个空的fifo。

2. asynchat示例

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

一旦头部被读取,如果请求的类型是POST(表示输入流中还有其他数据),则Content-Length:头部用于设置数字终结符以从通道读取适量的数据。

handle_request()在设置了通道终止符后,所有相关输入都被编组后,调用该方法None以确保忽略Web客户端发送的任何无关数据。

代码语言:javascript
复制
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 = ""
        self.set_terminator("\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("".join(self.ibuffer))
            self.ibuffer = []
            if self.op.upper() == "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, "".join(self.ibuffer))
            self.handling = True
            self.ibuffer = []
            self.handle_request()

扫码关注腾讯云开发者

领取腾讯云代金券