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

源代码: Lib / asynchat.py

版本3.6以后不推荐使用:asyncio改用。


注意

 

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

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

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对象将队列中的生成器移除,并开始使用下一个生成器(如果有)。当生成器队列为空时,该 handle_write()方法不执行任何操作。您可以使用通道对象的 set_terminator()方法来描述如何识别来自远程端点的传入传输的结束或重要断点。

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

async_chat.close_when_done()

将一个None打开到生成器队列。当这个生产者从队列中弹出时,它会导致通道关闭。

async_chat.collect_incoming_data数据

称为与数据保持接收到的数据的任意量。必须覆盖的默认方法会引发 NotImplementedError异常。

async_chat.discard_buffers()

在紧急情况下,此方法将丢弃输入和/或输出缓冲区和生成器队列中保存的任何数据。

async_chat.found_terminator()

当传入数据流与设置的终止条件匹配时调用set_terminator()。必须覆盖的默认方法会引发NotImplementedError异常。缓冲的输入数据应该可以通过实例属性获得。

async_chat.get_terminator()

返回通道的当前终止符。

async_chat.push数据

将数据推送到通道的队列以确保其传输。这就是让通道将数据写入网络所需要做的全部工作,例如,可以在更复杂的方案中使用您自己的生产者来实现加密和分块。

async_chat.push_with_producer制片人

获取生成器对象并将其添加到与通道关联的生产者队列中。当所有当前推送的生产者都已用尽时,通道将通过调用其more() 方法并将数据发送到远程端点来使用该生产者的数据。

async_chat.set_terminator期限

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

术语描述
found_terminator()在输入流中找到字符串时调用
整数found_terminator()在收到指定数量的字符时呼叫
None该频道将继续永久收集数据

请注意,found_terminator()调用后,通道后面的任何数据都可供通道读取。

asynchat示例

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

读取标头后,如果请求的类型为POST(表示输入流中存在更多数据),则 Content-Length:标头用于设置数字终结器以从通道读取正确数量的数据。

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

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()

转载于:https://my.oschina.net/u/3612528/blog/3050965

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值