Moduł "asyncore" --- Asynchroniczna obsługa gniazda
***************************************************

**Source code:** Lib/asyncore.py

Zdezaprobowane w wersji 3.6, zostanie usunięte w wersji 3.12: The
"asyncore" module is deprecated (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ł dostarcza podstawową infrastrukturę do pisania
asynchronicznych klientów i serwerów usługi gniazd.

Availability: not Emscripten, not WASI.

This module does not work or is not available on WebAssembly platforms
"wasm32-emscripten" and "wasm32-wasi". See WebAssembly platforms for
more information.

Istnieją tylko dwa sposoby aby program na pojedynczym procesorze robił
"więcej niż jedną rzecz na raz." Wielo-wątkowe programowanie jest
najprostszą i najczęściej spotykaną drogą aby to robić, ale istnieje
inna bardzo odmienna technika, która pozwala mieć prawie wszystkie
zalety wielowątkowości, bez używania wielu wątków. Jest ona tylko
pomocna jeśli twój program jest w większości związany z
wejściem/wyjściem. Jeśli twój program jest związany z procesorem,
wtedy wywłaszczające planowane wątki są najczęściej tym czego
potrzebujesz. Serwery sieciowe jednakże są rzadko związane z
procesorem.

If your operating system supports the "select()" system call in its
I/O library (and nearly all do), then you can use it to juggle
multiple communication channels at once; doing other work while your
I/O is taking place in the "background."  Although this strategy can
seem strange and complex, especially at first, it is in many ways
easier to understand and control than multi-threaded programming.  The
"asyncore" module solves many of the difficult problems for you,
making the task of building sophisticated high-performance network
servers and clients a snap.  For "conversational" applications and
protocols the companion "asynchat" module is invaluable.

Podstawowym pomysłem stojącym za oboma modułami jest stworzenie
jednego lub więcej *kanałów*, przykładów uogólnienia
"asyncore.dispatcher" i "asynchat.async_chat". Utworzenie kanałów
dodaje je do globalnej mapy, używanej przez funkcję "loop()" jeśli
dostarczysz jej swojej własnej *mapy*.

Gdy początkowy(e) kanał(y) jest(są) tworzony(e), wywołanie funkcji
"loop()" aktywuje usługę kanału, która kontynuuje zanim ostatni kanał
(włączając w to jakiekolwiek które zostały dodane do mapy podczas
asynchronicznej usługi) nie zostanie zamknięty.

asyncore.loop([timeout[, use_poll[, map[, count]]]])

   Enter a polling loop that terminates after count passes or all open
   channels have been closed.  All arguments are optional.  The
   *count* parameter defaults to "None", resulting in the loop
   terminating only when all channels have been closed.  The *timeout*
   argument sets the timeout parameter for the appropriate "select()"
   or "poll()" call, measured in seconds; the default is 30 seconds.
   The *use_poll* parameter, if true, indicates that "poll()" should
   be used in preference to "select()" (the default is "False").

   Parametr *map* jest słownikiem którego elementami są kanały do
   oglądania. Gdy kanały są zamykane są one kasowane z ich mapy. Jeśli
   *mapa* jest pominięta, nadrzędna mapa jest używana. Kanały
   (przykłady uogólnienia "asyncore.dispatcher" i
   "asynchat.async_chat" i podrzędne uogólnienia tychże) mogą dowolnie
   być mieszane wewnątrz mapy.

class asyncore.dispatcher

   Uogólnienie "dispatcher" jest cienkim opakowaniem wokół
   niskopoziomowego przedmiotu gniazda. Aby uczynić je bardziej
   użytecznym, ma kilka sposobów postępowania dla obsługi-zdarzeń
   które są wzywane z asynchronicznej pętli. Poza tym, może być
   traktowana jako zwyczajny nieblokujący przedmiot gniazda.

   Odpalanie niskopoziomowych zdarzeń w konkretnych momentach lub w
   konkretnych stanach połączeń mówi pętli asynchronicznej że
   konkretne wyższego poziomu zdarzenia miały miejsce. Dla przykładu,
   jeśli żądaliśmy aby gniazdo podłączone było do innego hosta, wiemy
   że połączenie zostało ustanowione gdy gniazdo stanie się możliwe do
   zapisania po raz pierwszy (w tym momencie wiesz że możesz zapisać
   do niego oczekując powodzenia). Dorozumiane zdarzenia wyższego
   poziomu to:

   +------------------------+------------------------------------------+
   | Zdarzenie              | Opis                                     |
   |========================|==========================================|
   | "handle_connect()"     | Domyślne przez pierwsze zdarzenie        |
   |                        | odczytu lub zapisu                       |
   +------------------------+------------------------------------------+
   | "handle_close()"       | Domyślne przy zdarzeniu odczytu bez      |
   |                        | dostępnych danych                        |
   +------------------------+------------------------------------------+
   | "handle_accepted()"    | Domyślne przy zdarzeniu czytania na      |
   |                        | nasłuchującym gnieździe                  |
   +------------------------+------------------------------------------+

   During asynchronous processing, each mapped channel's "readable()"
   and "writable()" methods are used to determine whether the
   channel's socket should be added to the list of channels
   "select()"ed or "poll()"ed for read and write events.

   Dlatego, zestaw zdarzeń kanałów jest większy, niż podstawowych
   zdarzeń gniazda. Pełny zestaw sposobów postępowania, które mogą być
   przesłonięte w twoim podrzędnym uogólnieniu jest następujący:

   handle_read()

      Wywoływane, gdy asynchroniczna pętla wykryje, że wywołanie
      "read()" na gnieździe kanału odniesie sukces.

   handle_write()

      Wywoływane, gdy asynchroniczna pętla wykryje, że możliwe do
      zapisu gniazdo może być zapisane. Często ten sposób postępowania
      będzie wypełniał konieczne wczytywanie z wyprzedzeniem dla
      poprawy wydajności. Dla przykładu:

         def handle_write(self):
             sent = self.send(self.buffer)
             self.buffer = self.buffer[sent:]

   handle_expt()

      Wywoływane gdy są dane poza zakresem (OOB) dla połączenia z
      gniazdem. To raczej nie wystąpi nigdy, jako że OOB jest rzadko
      wspierany i rzadziej jeszcze używany.

   handle_connect()

      Wywoływane gdy gniazdo aktywnego otwierającego właściwie wywoła
      połączenie. Może wysłać "powitalny" banner, lub zainicjować
      negocjację protokołu z zewnętrznym punktem końcowym, dla
      przykładu.

   handle_close()

      Wywoływany gdy gniazdo jest zamykane.

   handle_error()

      Wywoływane gdy wyjątek jest zgłaszany i nie jest inaczej
      obsługiwany. Domyślna wersja wypisuje skumulowany wypis.

   handle_accept()

      Called on listening channels (passive openers) when a connection
      can be established with a new remote endpoint that has issued a
      "connect()" call for the local endpoint. Deprecated in version
      3.2; use "handle_accepted()" instead.

      Niezalecane od wersji 3.2.

   handle_accepted(sock, addr)

      Called on listening channels (passive openers) when a connection
      has been established with a new remote endpoint that has issued
      a "connect()" call for the local endpoint.  *sock* is a *new*
      socket object usable to send and receive data on the connection,
      and *addr* is the address bound to the socket on the other end
      of the connection.

      Nowe w wersji 3.2.

   readable()

      Wywoływane za każdym razem dla asynchronicznej pętli aby
      ustalić, czy gniazdo kanału powinno być dodane do listy na
      której zdarzenia wczytywania mogą następować. Domyślny sposób po
      prostu zwraca "Prawdę" - z ang. - "True", wskazując że domyślnie
      wszystkie kanały będą zainteresowane zdarzeniami wczytywania.

   writable()

      Wywoływane za każdym razem dla asynchronicznej pętli aby
      ustalić, czy gniazdo kanału powinno być dodawane do listy na
      której zdarzenia zapisu mogą następować. Domyślny sposób
      postępowania po prostu zwraca "Prawdę" - z ang. - "True",
      wskazując że domyślnie, wszystkie kanały będą zainteresowane
      zdarzeniami zapisu.

   Na dodatek, każdy kanał deleguje lub rozszerza wiele ze sposobów
   postępowania gniazd. Większość z tych jest prawie identyczna z ich
   partnerami gniazda.

   create_socket(family=socket.AF_INET, type=socket.SOCK_STREAM)

      To jest identyczne z utworzeniem normalnego gniazda, i będzie
      używało tych samych opcji dla tworzenia. Zajrzyj do dokumentacji
      do "socket" po więcej informacji o tworzeniu gniazd.

      Zmienione w wersji 3.3: *family* and *type* arguments can be
      omitted.

   connect(address)

      Tak jak z normalnymi przedmiotami gniazd, *adres* - z ang. -
      *address* jest krotką z pierwszym elementem hosta do którego się
      podłącza, i drugim numerem portu.

   send(data)

      Prześlij *dane* - z ang. - *data* do odległego punktu końcowego
      gniazda.

   recv(buffer_size)

      Read at most *buffer_size* bytes from the socket's remote end-
      point.  An empty bytes object implies that the channel has been
      closed from the other end.

      Note that "recv()" may raise "BlockingIOError" , even though
      "select.select()" or "select.poll()" has reported the socket
      ready for reading.

   listen(backlog)

      Nasłuchuj połączeń wykonywanych do gniazda. Parametr *wstecznego
      logu* - z ang. - *backlog* określa maksymalną liczbę
      kolejkowanych połączeń i powinien być równy przynajmniej 1;
      Wartość maksymalna jest zależna od systemu (zwykle jest równa
      5).

   bind(address)

      Połącz gniazdo z *adresem*. Gniazdo nie może być już połączone z
      adresem. (Format *adresu* zależy od rodziny adresów --- zajrzyj
      do dokumentacji "socket" po więcej informacji.) Aby oznaczyć
      gniazdo jako możliwe do ponownego użycia - z ang. - re-usable
      (ustawiając opcję "SO_REUSEADDR"), wywołaj sposób postępowania
      "set_reuse_addr()" obiektu "dispatcher".

   accept()

      Accept a connection.  The socket must be bound to an address and
      listening for connections.  The return value can be either
      "None" or a pair "(conn, address)" where *conn* is a *new*
      socket object usable to send and receive data on the connection,
      and *address* is the address bound to the socket on the other
      end of the connection. When "None" is returned it means the
      connection didn't take place, in which case the server should
      just ignore this event and keep listening for further incoming
      connections.

   close()

      Zamknij gniazdo. Wszystkie przyszłe operacje na gnieździe
      zawiodą. Odległy koniec nie dostanie więcej danych (po tym jak
      zakolejkowane dane zostaną przesłane). Gniazda są automatycznie
      zamykane gdy są poddawane zbieraniu śmieci.

class asyncore.dispatcher_with_send

   A "dispatcher" subclass which adds simple buffered output
   capability, useful for simple clients. For more sophisticated usage
   use "asynchat.async_chat".

class asyncore.file_dispatcher

   A file_dispatcher takes a file descriptor or *file object* along
   with an optional map argument and wraps it for use with the
   "poll()" or "loop()" functions.  If provided a file object or
   anything with a "fileno()" method, that method will be called and
   passed to the "file_wrapper" constructor.

   Availability: Unix.

class asyncore.file_wrapper

   A file_wrapper takes an integer file descriptor and calls
   "os.dup()" to duplicate the handle so that the original handle may
   be closed independently of the file_wrapper.  This class implements
   sufficient methods to emulate a socket for use by the
   "file_dispatcher" class.

   Availability: Unix.


Podstawowy klient HTTP Przykładu asyncore
=========================================

Tu jest bardzo podstawowy klient HTTP który używa uogólnienia
"dispatcher" do wypełnienia jego obsługi gniazda:

   import asyncore

   class HTTPClient(asyncore.dispatcher):

       def __init__(self, host, path):
           asyncore.dispatcher.__init__(self)
           self.create_socket()
           self.connect( (host, 80) )
           self.buffer = bytes('GET %s HTTP/1.0\r\nHost: %s\r\n\r\n' %
                               (path, host), 'ascii')

       def handle_connect(self):
           pass

       def handle_close(self):
           self.close()

       def handle_read(self):
           print(self.recv(8192))

       def writable(self):
           return (len(self.buffer) > 0)

       def handle_write(self):
           sent = self.send(self.buffer)
           self.buffer = self.buffer[sent:]


   client = HTTPClient('www.python.org', '/')
   asyncore.loop()


asyncore Example basic echo server
==================================

Here is a basic echo server that uses the "dispatcher" class to accept
connections and dispatches the incoming connections to a handler:

   import asyncore

   class EchoHandler(asyncore.dispatcher_with_send):

       def handle_read(self):
           data = self.recv(8192)
           if data:
               self.send(data)

   class EchoServer(asyncore.dispatcher):

       def __init__(self, host, port):
           asyncore.dispatcher.__init__(self)
           self.create_socket()
           self.set_reuse_addr()
           self.bind((host, port))
           self.listen(5)

       def handle_accepted(self, sock, addr):
           print('Incoming connection from %s' % repr(addr))
           handler = EchoHandler(sock)

   server = EchoServer('localhost', 8080)
   asyncore.loop()
