asynchat
— Asynchronous 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.dispatcher
和asynchat.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
通道对象。
-
class
asynchat.
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 meaningfulcollect_incoming_data()
andfound_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 aselect()
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
允许您定义producers的FIFO队列。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 methodscollect_incoming_data()
andfound_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 streamfound_terminator()
integer
Will call收到指定数量的字符后,将调用found_terminator()
when the indicated number of characters have been receivedfound_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 web服务器可能会为每个传入的客户端连接创建http_request_handler
object for each incoming client connection. 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 读取标头后,如果请求类型为POST(指示输入流中存在更多数据),则使用Content-Length:
header is used to set a numeric terminator to read the right amount of data from the channel.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()