asynchatAsynchronous socket command/response handler异步套接字命令/响应处理程序

Source code: Lib/asynchat.py

Deprecated since version 3.6: 自3.6版起已弃用:asynchat will be removed in Python 3.12 (PEP 594). asynchat将在Python 3.12(PEP 594)中删除。Please use asyncio instead.请改用asyncio


Note

This module exists for backwards compatibility only. 此模块仅用于向后兼容。For new code we recommend using asyncio.对于新代码,我们建议使用asyncio

This module builds on the asyncore infrastructure, simplifying asynchronous clients and servers and making it easier to handle protocols whose elements are terminated by arbitrary strings, or are of variable length. 该模块构建在asyncore基础设施上,简化了异步客户端和服务器,使其更容易处理元素由任意字符串终止或长度可变的协议。asynchat defines the abstract class async_chat that you subclass, providing implementations of the collect_incoming_data() and found_terminator() methods. asynchat定义了子类的抽象类async_chat,提供了collect_incoming_data()found_terminator()方法的实现。It uses the same asynchronous loop as asyncore, and the two types of channel, asyncore.dispatcher and asynchat.async_chat, can freely be mixed in the channel map. 它使用与asyncore相同的异步循环,并且可以在通道映射中自由混合使用asyncore.dispatcherasynchat.async_chat这两种类型的通道。Typically an asyncore.dispatcher server channel generates new asynchat.async_chat channel objects as it receives incoming connection requests.通常,asyncore.dispatcher服务器通道在接收传入连接请求时会生成新的asynchat.async_chat通道对象。

classasynchat.async_chat

This class is an abstract subclass of asyncore.dispatcher. 此类是asyncore.dispatcher的抽象子类。To make practical use of the code you must subclass async_chat, providing meaningful collect_incoming_data() and found_terminator() methods. 要实际使用代码,必须子类async_chat,提供有意义的collect_incoming_data()found_terminator()方法。The asyncore.dispatcher methods can be used, although not all make sense in a message/response context.可以使用asyncore.dispatcher方法,尽管在消息/响应上下文中并非所有方法都有意义。

Like asyncore.dispatcher, async_chat defines a set of events that are generated by an analysis of socket conditions after a select() call. asyncore.dispatcher一样,async_chat定义了一组事件,这些事件是在select()调用后通过分析套接字条件生成的。Once the polling loop has been started the async_chat object’s methods are called by the event-processing framework with no action on the part of the programmer.轮询循环启动后,事件处理框架将调用async_chat对象的方法,程序员无需执行任何操作。

Two class attributes can be modified, to improve performance, or possibly even to conserve memory.可以修改两个类属性,以提高性能,甚至可能节省内存。

ac_in_buffer_size

The asynchronous input buffer size (default 4096).异步输入缓冲区大小(默认为4096)。

ac_out_buffer_size

The asynchronous output buffer size (default 4096).异步输出缓冲区大小(默认为4096)。

Unlike asyncore.dispatcher, async_chat allows you to define a FIFO queue of producers. asyncore.dispatcher不同,async_chat允许您定义producersFIFO队列。A producer need have only one method, more(), which should return data to be transmitted on the channel. 生产者只需要一个方法more(),它应该返回要在信道上传输的数据。The producer indicates exhaustion (i.e. that it contains no more data) by having its more() method return the empty bytes object. 生产者通过让其more()方法返回空字节对象来表示耗尽(即它不再包含数据)。At this point the async_chat object removes the producer from the queue and starts using the next producer, if any. 此时,async_chat对象从队列中删除生产者,并开始使用下一个生产者(如果有的话)。When the producer queue is empty the handle_write() method does nothing. 当生产者队列为空时,handle_write()方法不执行任何操作。You use the channel object’s set_terminator() method to describe how to recognize the end of, or an important breakpoint in, an incoming transmission from the remote endpoint.您可以使用通道对象的set_terminator()方法来描述如何识别来自远程端点的传入传输的结束或重要断点。

To build a functioning async_chat subclass your input methods collect_incoming_data() and found_terminator() must handle the data that the channel receives asynchronously. 要构建一个运行的async_chat子类,输入方法collect_incoming_data()found_terminator()必须处理通道异步接收的数据。The methods are described below.方法如下所述。

async_chat.close_when_done()

Pushes a None on to the producer queue. None推送到生产者队列。When this producer is popped off the queue it causes the channel to be closed.当此生产者从队列中弹出时,它会导致频道关闭。

async_chat.collect_incoming_data(data)

Called with data holding an arbitrary amount of received data. 使用保存任意数量的接收数据的data调用。The default method, which must be overridden, raises a NotImplementedError exception.必须重写的默认方法引发NotImplementedError异常。

async_chat.discard_buffers()

In emergencies this method will discard any data held in the input and/or output buffers and the producer queue.在紧急情况下,此方法将丢弃保存在输入和/或输出缓冲区和生产者队列中的任何数据。

async_chat.found_terminator()

Called when the incoming data stream matches the termination condition set by set_terminator(). 当传入数据流与set_terminator()设置的终止条件匹配时调用。The default method, which must be overridden, raises a NotImplementedError exception. 必须重写的默认方法引发NotImplementedError异常。The buffered input data should be available via an instance attribute.缓冲的输入数据应该通过实例属性可用。

async_chat.get_terminator()

Returns the current terminator for the channel.返回通道的当前终止符。

async_chat.push(data)

Pushes data on to the channel’s queue to ensure its transmission. 将数据推送到通道的队列以确保其传输。This is all you need to do to have the channel write the data out to the network, although it is possible to use your own producers in more complex schemes to implement encryption and chunking, for example.这就是让频道将数据写入网络所需要做的一切,尽管可以在更复杂的方案中使用自己的生产者来实现加密和分块。

async_chat.push_with_producer(producer)

Takes a producer object and adds it to the producer queue associated with the channel. 获取生产者对象并将其添加到与频道关联的生产者队列中。When all currently-pushed producers have been exhausted the channel will consume this producer’s data by calling its more() method and send the data to the remote endpoint.当所有当前推送的生产者都已耗尽时,通道将通过调用其more()方法来消耗该生产者的数据,并将数据发送到远程端点。

async_chat.set_terminator(term)

Sets the terminating condition to be recognized on the channel. 设置要在通道上识别的终止条件。term may be any of three types of value, corresponding to three different ways to handle incoming protocol data.term可以是三种类型的值中的任何一种,对应于处理传入协议数据的三种不同方式。

term术语

Description描述

string

Will call found_terminator() when the string is found in the input stream当在输入流中找到字符串时,将调用found_terminator()

integer

Will call found_terminator() when the indicated number of characters have been received收到指定数量的字符后,将调用found_terminator()

None

The channel continues to collect data forever该频道将永远收集数据

Note that any data following the terminator will be available for reading by the channel after found_terminator() is called.请注意,在调用found_terminator()后,终止符后面的任何数据都可以由通道读取。

asynchat Example

The following partial example shows how HTTP requests can be read with async_chat. 下面的部分示例显示了如何使用async_chat读取HTTP请求。A web server might create an http_request_handler object for each incoming client connection. web服务器可能会为每个传入的客户端连接创建http_request_handler对象。Notice that initially the channel terminator is set to match the blank line at the end of the HTTP headers, and a flag indicates that the headers are being read.请注意,最初通道终止符被设置为与HTTP标头末尾的空白行相匹配,并且一个标志指示正在读取标头。

Once the headers have been read, if the request is of type POST (indicating that further data are present in the input stream) then the Content-Length: header is used to set a numeric terminator to read the right amount of data from the channel.读取标头后,如果请求类型为POST(指示输入流中存在更多数据),则使用Content-Length:标头设置数字终止符,以从通道中读取正确数量的数据。

The handle_request() method is called once all relevant input has been marshalled, after setting the channel terminator to None to ensure that any extraneous data sent by the web client are ignored.在将通道终止符设置为None以确保忽略web客户端发送的任何无关数据之后,一旦整理了所有相关输入,就会调用handle_request()方法。

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