asynchat — Asynchroniczna obsługa gniazda komend/odpowiedzi.

Source code: Lib/asynchat.py

Niezalecane od wersji 3.6: asynchat will be removed in Python 3.12 (see PEP 594 for details). Please use asyncio instead.


Informacja

This module exists for backwards compatibility only. For new code we recommend using asyncio.

Ten moduł buduje na infrastrukturze modułu asyncore, upraszczając klientów i serwery asynchroniczne i czyniąc łatwiejszym obsługę protokołów których elementy są zakańczane przez zadane ciągi znaków, lub są zmiennej długości. Moduł asynchat określa abstrakcyjne uogólnienie async_chat które możesz dostosować tworząc własne podrzędne uogólnienie, dostarczając wypełnień sposobów postępowania collect_incoming_data() i found_terminator(). Używa tej samej asynchronicznej pętli co moduł asyncore, i dwóch rodzajów kanałów, - asyncore.dispatcher i asynchat.async_chat, mogą być dowolnie być mieszane w mapie kanałów. Typowo kanał serwera asyncore.dispatcher generuje nowe obiekty kanałów asynchat.async_chat gdy otrzymuje wchodzące zapytania o połączenie.

class asynchat.async_chat

To uogólnienie jest abstrakcyjnym uogólnieniem podrzędnym względem uogólnienia asyncore.dispatcher. Aby praktycznie użyć kodu musisz dostosować podrzędne uogólnienie względem uogólnienia async_chat, dostarczając sensownego wypełnienia sposobu postępowania collect_incoming_data() i sposobu postępowania found_terminator(). Sposoby postępowania uogólnienia asyncore.dispatcher mogą być używane, chociaż nie wszystkie mają sens w kontekście wiadomość/odpowiedź.

Like asyncore.dispatcher, async_chat defines a set of events that are generated by an analysis of socket conditions after a select() call. 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.

Dwie właściwości uogólnienia mogą być modyfikowane, aby poprawić wydajność, lub nawet aby możliwie oszczędzać pamięć.

ac_in_buffer_size

Rozmiar przestrzeni wymiany wejściowej asynchronicznej (domyślnie 4096).

ac_out_buffer_size

Rozmiar przestrzeni wymiany wyjściowej asynchronicznej (domyślnie 4096).

Unlike asyncore.dispatcher, async_chat allows you to define a FIFO queue of producers. A producer need have only one method, more(), which should return data to be transmitted on the channel. The producer indicates exhaustion (i.e. that it contains no more data) by having its more() method return the empty bytes object. At this point the async_chat object removes the producer from the queue and starts using the next producer, if any. When the producer queue is empty the handle_write() method does nothing. 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.

Aby zbudować funkcjonujące podrzędne uogólnienia względem uogólnienia async_chat, twoje sposoby postępowania wprowadzania collect_incoming_data() i found_terminator() muszą obsługiwać dane które kanał otrzymuje asynchronicznie. Sposoby postępowania są opisane poniżej.

async_chat.close_when_done()

Pushes a None on to the producer queue. When this producer is popped off the queue it causes the channel to be closed.

async_chat.collect_incoming_data(data)

Wywoływany z danymi przechowując określoną ilość otrzymanych danych. Domyślny sposób postępowania, który musi zostać przesłonięty, zgłasza wyjątek 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()

Wywoływana gdy przychodzący strumień danych odpowiada warunkowi zakończenia ustawionemu przez sposób postępowania set_terminator(). Domyślny sposób postępowania, który musi być przesłonięty, zgłasza wyjątek NotImplementedError. Dane wejściowe z przestrzeni wymiany powinny być dostępne przez właściwość przykładu.

async_chat.get_terminator()

Zwraca obecne zakończenie dla kanału.

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.

async_chat.set_terminator(term)

Ustawia warunek zakończenia aby był rozpoznany przez kanał. term może być dowolną z trzech typów wartości, odpowiadających trzem różnym sposobom obsługi przychodzących danych protokołu.

term - z ang. - termin

Opis

ciąg znaków

Wywoła sposób postępowania found_terminator() gdy ciąg znaków zostanie znaleziony w strumieniu wejściowym

integer - z ang. - liczba całkowita

Wywoła found_terminator() gdy wskazana liczba znaków zostanie odebrana

None - z ang. - Żaden

Kanał nadal zbiera dane w pętli nieskończonej

Zauważ że dowolne dane następujące po terminatorze będą dostępne dla przeczytania przez kanał po tym jak sposób postępowania found_terminator() zostanie wywołany.

Przykład asynchat

Następujący częściowy przykład pokazuje jak zapytania HTTP mogą być wczytane za pomocą async_chat. Serwer sieci może tworzyć obiekt http_request_handler dla każdego przychodzącego połączenia klienckiego. Zauważ że początkowo zakończenie kanału jest ustalone aby odpowiadało pustej linii na końcu nagłówka HTTP, i flaga wskazująca że nagłówki są wczytywane.

Gdy już nagłówki zostaną wczytane, jeśli zapytanie jest typu POST (wskazując na to że dalsze dane są obecne w strumieniu wejściowym) wtedy nagłówek Content-Length: jest używany aby ustawić numeryczny terminator do wczytania właściwej ilości danych z kanału.

Metoda handle_request() jest wywoływane gdy już całe istotne wejście zostało pobrane, po ustawieniu terminatora kanału na None - z ang. - Żaden aby upewnić się że jakiekolwiek nadmiarowe dane przesyłane przez klienta sieci są ignorowane.

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