17db96d56Sopenharmony_ci:mod:`asyncore` --- Asynchronous socket handler
27db96d56Sopenharmony_ci===============================================
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_ci.. module:: asyncore
57db96d56Sopenharmony_ci   :synopsis: A base class for developing asynchronous socket handling
67db96d56Sopenharmony_ci              services.
77db96d56Sopenharmony_ci   :deprecated:
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci.. moduleauthor:: Sam Rushing <rushing@nightmare.com>
107db96d56Sopenharmony_ci.. sectionauthor:: Christopher Petrilli <petrilli@amber.org>
117db96d56Sopenharmony_ci.. sectionauthor:: Steve Holden <sholden@holdenweb.com>
127db96d56Sopenharmony_ci.. heavily adapted from original documentation by Sam Rushing
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ci**Source code:** :source:`Lib/asyncore.py`
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ci.. deprecated-removed:: 3.6 3.12
177db96d56Sopenharmony_ci   The :mod:`asyncore` module is deprecated
187db96d56Sopenharmony_ci   (see :pep:`PEP 594 <594#asyncore>` for details).
197db96d56Sopenharmony_ci   Please use :mod:`asyncio` instead.
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_ci--------------
227db96d56Sopenharmony_ci
237db96d56Sopenharmony_ci.. note::
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ci   This module exists for backwards compatibility only.  For new code we
267db96d56Sopenharmony_ci   recommend using :mod:`asyncio`.
277db96d56Sopenharmony_ci
287db96d56Sopenharmony_ciThis module provides the basic infrastructure for writing asynchronous  socket
297db96d56Sopenharmony_ciservice clients and servers.
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ci.. include:: ../includes/wasm-notavail.rst
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ciThere are only two ways to have a program on a single processor do  "more than
347db96d56Sopenharmony_cione thing at a time." Multi-threaded programming is the  simplest and most
357db96d56Sopenharmony_cipopular way to do it, but there is another very different technique, that lets
367db96d56Sopenharmony_ciyou have nearly all the advantages of  multi-threading, without actually using
377db96d56Sopenharmony_cimultiple threads.  It's really  only practical if your program is largely I/O
387db96d56Sopenharmony_cibound.  If your program is processor bound, then pre-emptive scheduled threads
397db96d56Sopenharmony_ciare probably what you really need.  Network servers are rarely processor
407db96d56Sopenharmony_cibound, however.
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ciIf your operating system supports the :c:func:`select` system call in its I/O
437db96d56Sopenharmony_cilibrary (and nearly all do), then you can use it to juggle multiple
447db96d56Sopenharmony_cicommunication channels at once; doing other work while your I/O is taking
457db96d56Sopenharmony_ciplace in the "background."  Although this strategy can seem strange and
467db96d56Sopenharmony_cicomplex, especially at first, it is in many ways easier to understand and
477db96d56Sopenharmony_cicontrol than multi-threaded programming.  The :mod:`asyncore` module solves
487db96d56Sopenharmony_cimany of the difficult problems for you, making the task of building
497db96d56Sopenharmony_cisophisticated high-performance network servers and clients a snap.  For
507db96d56Sopenharmony_ci"conversational" applications and protocols the companion :mod:`asynchat`
517db96d56Sopenharmony_cimodule is invaluable.
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ciThe basic idea behind both modules is to create one or more network
547db96d56Sopenharmony_ci*channels*, instances of class :class:`asyncore.dispatcher` and
557db96d56Sopenharmony_ci:class:`asynchat.async_chat`.  Creating the channels adds them to a global
567db96d56Sopenharmony_cimap, used by the :func:`loop` function if you do not provide it with your own
577db96d56Sopenharmony_ci*map*.
587db96d56Sopenharmony_ci
597db96d56Sopenharmony_ciOnce the initial channel(s) is(are) created, calling the :func:`loop` function
607db96d56Sopenharmony_ciactivates channel service, which continues until the last channel (including
617db96d56Sopenharmony_ciany that have been added to the map during asynchronous service) is closed.
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ci.. function:: loop([timeout[, use_poll[, map[,count]]]])
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci   Enter a polling loop that terminates after count passes or all open
677db96d56Sopenharmony_ci   channels have been closed.  All arguments are optional.  The *count*
687db96d56Sopenharmony_ci   parameter defaults to ``None``, resulting in the loop terminating only when all
697db96d56Sopenharmony_ci   channels have been closed.  The *timeout* argument sets the timeout
707db96d56Sopenharmony_ci   parameter for the appropriate :func:`~select.select` or :func:`~select.poll`
717db96d56Sopenharmony_ci   call, measured in seconds; the default is 30 seconds.  The *use_poll*
727db96d56Sopenharmony_ci   parameter, if true, indicates that :func:`~select.poll` should be used in
737db96d56Sopenharmony_ci   preference to :func:`~select.select` (the default is ``False``).
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_ci   The *map* parameter is a dictionary whose items are the channels to watch.
767db96d56Sopenharmony_ci   As channels are closed they are deleted from their map.  If *map* is
777db96d56Sopenharmony_ci   omitted, a global map is used. Channels (instances of
787db96d56Sopenharmony_ci   :class:`asyncore.dispatcher`, :class:`asynchat.async_chat` and subclasses
797db96d56Sopenharmony_ci   thereof) can freely be mixed in the map.
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ci
827db96d56Sopenharmony_ci.. class:: dispatcher()
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ci   The :class:`dispatcher` class is a thin wrapper around a low-level socket
857db96d56Sopenharmony_ci   object. To make it more useful, it has a few methods for event-handling
867db96d56Sopenharmony_ci   which are called from the asynchronous loop.   Otherwise, it can be treated
877db96d56Sopenharmony_ci   as a normal non-blocking socket object.
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_ci   The firing of low-level events at certain times or in certain connection
907db96d56Sopenharmony_ci   states tells the asynchronous loop that certain higher-level events have
917db96d56Sopenharmony_ci   taken place.  For example, if we have asked for a socket to connect to
927db96d56Sopenharmony_ci   another host, we know that the connection has been made when the socket
937db96d56Sopenharmony_ci   becomes writable for the first time (at this point you know that you may
947db96d56Sopenharmony_ci   write to it with the expectation of success).  The implied higher-level
957db96d56Sopenharmony_ci   events are:
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ci   +----------------------+----------------------------------------+
987db96d56Sopenharmony_ci   | Event                | Description                            |
997db96d56Sopenharmony_ci   +======================+========================================+
1007db96d56Sopenharmony_ci   | ``handle_connect()`` | Implied by the first read or write     |
1017db96d56Sopenharmony_ci   |                      | event                                  |
1027db96d56Sopenharmony_ci   +----------------------+----------------------------------------+
1037db96d56Sopenharmony_ci   | ``handle_close()``   | Implied by a read event with no data   |
1047db96d56Sopenharmony_ci   |                      | available                              |
1057db96d56Sopenharmony_ci   +----------------------+----------------------------------------+
1067db96d56Sopenharmony_ci   | ``handle_accepted()``| Implied by a read event on a listening |
1077db96d56Sopenharmony_ci   |                      | socket                                 |
1087db96d56Sopenharmony_ci   +----------------------+----------------------------------------+
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci   During asynchronous processing, each mapped channel's :meth:`readable` and
1117db96d56Sopenharmony_ci   :meth:`writable` methods are used to determine whether the channel's socket
1127db96d56Sopenharmony_ci   should be added to the list of channels :c:func:`select`\ ed or
1137db96d56Sopenharmony_ci   :c:func:`poll`\ ed for read and write events.
1147db96d56Sopenharmony_ci
1157db96d56Sopenharmony_ci   Thus, the set of channel events is larger than the basic socket events.  The
1167db96d56Sopenharmony_ci   full set of methods that can be overridden in your subclass follows:
1177db96d56Sopenharmony_ci
1187db96d56Sopenharmony_ci
1197db96d56Sopenharmony_ci   .. method:: handle_read()
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_ci      Called when the asynchronous loop detects that a :meth:`read` call on the
1227db96d56Sopenharmony_ci      channel's socket will succeed.
1237db96d56Sopenharmony_ci
1247db96d56Sopenharmony_ci
1257db96d56Sopenharmony_ci   .. method:: handle_write()
1267db96d56Sopenharmony_ci
1277db96d56Sopenharmony_ci      Called when the asynchronous loop detects that a writable socket can be
1287db96d56Sopenharmony_ci      written.  Often this method will implement the necessary buffering for
1297db96d56Sopenharmony_ci      performance.  For example::
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_ci         def handle_write(self):
1327db96d56Sopenharmony_ci             sent = self.send(self.buffer)
1337db96d56Sopenharmony_ci             self.buffer = self.buffer[sent:]
1347db96d56Sopenharmony_ci
1357db96d56Sopenharmony_ci
1367db96d56Sopenharmony_ci   .. method:: handle_expt()
1377db96d56Sopenharmony_ci
1387db96d56Sopenharmony_ci      Called when there is out of band (OOB) data for a socket connection.  This
1397db96d56Sopenharmony_ci      will almost never happen, as OOB is tenuously supported and rarely used.
1407db96d56Sopenharmony_ci
1417db96d56Sopenharmony_ci
1427db96d56Sopenharmony_ci   .. method:: handle_connect()
1437db96d56Sopenharmony_ci
1447db96d56Sopenharmony_ci      Called when the active opener's socket actually makes a connection.  Might
1457db96d56Sopenharmony_ci      send a "welcome" banner, or initiate a protocol negotiation with the
1467db96d56Sopenharmony_ci      remote endpoint, for example.
1477db96d56Sopenharmony_ci
1487db96d56Sopenharmony_ci
1497db96d56Sopenharmony_ci   .. method:: handle_close()
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_ci      Called when the socket is closed.
1527db96d56Sopenharmony_ci
1537db96d56Sopenharmony_ci
1547db96d56Sopenharmony_ci   .. method:: handle_error()
1557db96d56Sopenharmony_ci
1567db96d56Sopenharmony_ci      Called when an exception is raised and not otherwise handled.  The default
1577db96d56Sopenharmony_ci      version prints a condensed traceback.
1587db96d56Sopenharmony_ci
1597db96d56Sopenharmony_ci
1607db96d56Sopenharmony_ci   .. method:: handle_accept()
1617db96d56Sopenharmony_ci
1627db96d56Sopenharmony_ci      Called on listening channels (passive openers) when a connection can be
1637db96d56Sopenharmony_ci      established with a new remote endpoint that has issued a :meth:`connect`
1647db96d56Sopenharmony_ci      call for the local endpoint. Deprecated in version 3.2; use
1657db96d56Sopenharmony_ci      :meth:`handle_accepted` instead.
1667db96d56Sopenharmony_ci
1677db96d56Sopenharmony_ci      .. deprecated:: 3.2
1687db96d56Sopenharmony_ci
1697db96d56Sopenharmony_ci
1707db96d56Sopenharmony_ci   .. method:: handle_accepted(sock, addr)
1717db96d56Sopenharmony_ci
1727db96d56Sopenharmony_ci      Called on listening channels (passive openers) when a connection has been
1737db96d56Sopenharmony_ci      established with a new remote endpoint that has issued a :meth:`connect`
1747db96d56Sopenharmony_ci      call for the local endpoint.  *sock* is a *new* socket object usable to
1757db96d56Sopenharmony_ci      send and receive data on the connection, and *addr* is the address
1767db96d56Sopenharmony_ci      bound to the socket on the other end of the connection.
1777db96d56Sopenharmony_ci
1787db96d56Sopenharmony_ci      .. versionadded:: 3.2
1797db96d56Sopenharmony_ci
1807db96d56Sopenharmony_ci
1817db96d56Sopenharmony_ci   .. method:: readable()
1827db96d56Sopenharmony_ci
1837db96d56Sopenharmony_ci      Called each time around the asynchronous loop to determine whether a
1847db96d56Sopenharmony_ci      channel's socket should be added to the list on which read events can
1857db96d56Sopenharmony_ci      occur.  The default method simply returns ``True``, indicating that by
1867db96d56Sopenharmony_ci      default, all channels will be interested in read events.
1877db96d56Sopenharmony_ci
1887db96d56Sopenharmony_ci
1897db96d56Sopenharmony_ci   .. method:: writable()
1907db96d56Sopenharmony_ci
1917db96d56Sopenharmony_ci      Called each time around the asynchronous loop to determine whether a
1927db96d56Sopenharmony_ci      channel's socket should be added to the list on which write events can
1937db96d56Sopenharmony_ci      occur.  The default method simply returns ``True``, indicating that by
1947db96d56Sopenharmony_ci      default, all channels will be interested in write events.
1957db96d56Sopenharmony_ci
1967db96d56Sopenharmony_ci
1977db96d56Sopenharmony_ci   In addition, each channel delegates or extends many of the socket methods.
1987db96d56Sopenharmony_ci   Most of these are nearly identical to their socket partners.
1997db96d56Sopenharmony_ci
2007db96d56Sopenharmony_ci
2017db96d56Sopenharmony_ci   .. method:: create_socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
2027db96d56Sopenharmony_ci
2037db96d56Sopenharmony_ci      This is identical to the creation of a normal socket, and will use the
2047db96d56Sopenharmony_ci      same options for creation.  Refer to the :mod:`socket` documentation for
2057db96d56Sopenharmony_ci      information on creating sockets.
2067db96d56Sopenharmony_ci
2077db96d56Sopenharmony_ci      .. versionchanged:: 3.3
2087db96d56Sopenharmony_ci         *family* and *type* arguments can be omitted.
2097db96d56Sopenharmony_ci
2107db96d56Sopenharmony_ci
2117db96d56Sopenharmony_ci   .. method:: connect(address)
2127db96d56Sopenharmony_ci
2137db96d56Sopenharmony_ci      As with the normal socket object, *address* is a tuple with the first
2147db96d56Sopenharmony_ci      element the host to connect to, and the second the port number.
2157db96d56Sopenharmony_ci
2167db96d56Sopenharmony_ci
2177db96d56Sopenharmony_ci   .. method:: send(data)
2187db96d56Sopenharmony_ci
2197db96d56Sopenharmony_ci      Send *data* to the remote end-point of the socket.
2207db96d56Sopenharmony_ci
2217db96d56Sopenharmony_ci
2227db96d56Sopenharmony_ci   .. method:: recv(buffer_size)
2237db96d56Sopenharmony_ci
2247db96d56Sopenharmony_ci      Read at most *buffer_size* bytes from the socket's remote end-point.  An
2257db96d56Sopenharmony_ci      empty bytes object implies that the channel has been closed from the
2267db96d56Sopenharmony_ci      other end.
2277db96d56Sopenharmony_ci
2287db96d56Sopenharmony_ci      Note that :meth:`recv` may raise :exc:`BlockingIOError` , even though
2297db96d56Sopenharmony_ci      :func:`select.select` or :func:`select.poll` has reported the socket
2307db96d56Sopenharmony_ci      ready for reading.
2317db96d56Sopenharmony_ci
2327db96d56Sopenharmony_ci
2337db96d56Sopenharmony_ci   .. method:: listen(backlog)
2347db96d56Sopenharmony_ci
2357db96d56Sopenharmony_ci      Listen for connections made to the socket.  The *backlog* argument
2367db96d56Sopenharmony_ci      specifies the maximum number of queued connections and should be at least
2377db96d56Sopenharmony_ci      1; the maximum value is system-dependent (usually 5).
2387db96d56Sopenharmony_ci
2397db96d56Sopenharmony_ci
2407db96d56Sopenharmony_ci   .. method:: bind(address)
2417db96d56Sopenharmony_ci
2427db96d56Sopenharmony_ci      Bind the socket to *address*.  The socket must not already be bound.  (The
2437db96d56Sopenharmony_ci      format of *address* depends on the address family --- refer to the
2447db96d56Sopenharmony_ci      :mod:`socket` documentation for more information.)  To mark
2457db96d56Sopenharmony_ci      the socket as re-usable (setting the :const:`SO_REUSEADDR` option), call
2467db96d56Sopenharmony_ci      the :class:`dispatcher` object's :meth:`set_reuse_addr` method.
2477db96d56Sopenharmony_ci
2487db96d56Sopenharmony_ci
2497db96d56Sopenharmony_ci   .. method:: accept()
2507db96d56Sopenharmony_ci
2517db96d56Sopenharmony_ci      Accept a connection.  The socket must be bound to an address and listening
2527db96d56Sopenharmony_ci      for connections.  The return value can be either ``None`` or a pair
2537db96d56Sopenharmony_ci      ``(conn, address)`` where *conn* is a *new* socket object usable to send
2547db96d56Sopenharmony_ci      and receive data on the connection, and *address* is the address bound to
2557db96d56Sopenharmony_ci      the socket on the other end of the connection.
2567db96d56Sopenharmony_ci      When ``None`` is returned it means the connection didn't take place, in
2577db96d56Sopenharmony_ci      which case the server should just ignore this event and keep listening
2587db96d56Sopenharmony_ci      for further incoming connections.
2597db96d56Sopenharmony_ci
2607db96d56Sopenharmony_ci
2617db96d56Sopenharmony_ci   .. method:: close()
2627db96d56Sopenharmony_ci
2637db96d56Sopenharmony_ci      Close the socket.  All future operations on the socket object will fail.
2647db96d56Sopenharmony_ci      The remote end-point will receive no more data (after queued data is
2657db96d56Sopenharmony_ci      flushed).  Sockets are automatically closed when they are
2667db96d56Sopenharmony_ci      garbage-collected.
2677db96d56Sopenharmony_ci
2687db96d56Sopenharmony_ci
2697db96d56Sopenharmony_ci.. class:: dispatcher_with_send()
2707db96d56Sopenharmony_ci
2717db96d56Sopenharmony_ci   A :class:`dispatcher` subclass which adds simple buffered output capability,
2727db96d56Sopenharmony_ci   useful for simple clients. For more sophisticated usage use
2737db96d56Sopenharmony_ci   :class:`asynchat.async_chat`.
2747db96d56Sopenharmony_ci
2757db96d56Sopenharmony_ci.. class:: file_dispatcher()
2767db96d56Sopenharmony_ci
2777db96d56Sopenharmony_ci   A file_dispatcher takes a file descriptor or :term:`file object` along
2787db96d56Sopenharmony_ci   with an optional map argument and wraps it for use with the :c:func:`poll`
2797db96d56Sopenharmony_ci   or :c:func:`loop` functions.  If provided a file object or anything with a
2807db96d56Sopenharmony_ci   :c:func:`fileno` method, that method will be called and passed to the
2817db96d56Sopenharmony_ci   :class:`file_wrapper` constructor.
2827db96d56Sopenharmony_ci
2837db96d56Sopenharmony_ci   .. availability:: Unix.
2847db96d56Sopenharmony_ci
2857db96d56Sopenharmony_ci.. class:: file_wrapper()
2867db96d56Sopenharmony_ci
2877db96d56Sopenharmony_ci   A file_wrapper takes an integer file descriptor and calls :func:`os.dup` to
2887db96d56Sopenharmony_ci   duplicate the handle so that the original handle may be closed independently
2897db96d56Sopenharmony_ci   of the file_wrapper.  This class implements sufficient methods to emulate a
2907db96d56Sopenharmony_ci   socket for use by the :class:`file_dispatcher` class.
2917db96d56Sopenharmony_ci
2927db96d56Sopenharmony_ci   .. availability:: Unix.
2937db96d56Sopenharmony_ci
2947db96d56Sopenharmony_ci
2957db96d56Sopenharmony_ci.. _asyncore-example-1:
2967db96d56Sopenharmony_ci
2977db96d56Sopenharmony_ciasyncore Example basic HTTP client
2987db96d56Sopenharmony_ci----------------------------------
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_ciHere is a very basic HTTP client that uses the :class:`dispatcher` class to
3017db96d56Sopenharmony_ciimplement its socket handling::
3027db96d56Sopenharmony_ci
3037db96d56Sopenharmony_ci   import asyncore
3047db96d56Sopenharmony_ci
3057db96d56Sopenharmony_ci   class HTTPClient(asyncore.dispatcher):
3067db96d56Sopenharmony_ci
3077db96d56Sopenharmony_ci       def __init__(self, host, path):
3087db96d56Sopenharmony_ci           asyncore.dispatcher.__init__(self)
3097db96d56Sopenharmony_ci           self.create_socket()
3107db96d56Sopenharmony_ci           self.connect( (host, 80) )
3117db96d56Sopenharmony_ci           self.buffer = bytes('GET %s HTTP/1.0\r\nHost: %s\r\n\r\n' %
3127db96d56Sopenharmony_ci                               (path, host), 'ascii')
3137db96d56Sopenharmony_ci
3147db96d56Sopenharmony_ci       def handle_connect(self):
3157db96d56Sopenharmony_ci           pass
3167db96d56Sopenharmony_ci
3177db96d56Sopenharmony_ci       def handle_close(self):
3187db96d56Sopenharmony_ci           self.close()
3197db96d56Sopenharmony_ci
3207db96d56Sopenharmony_ci       def handle_read(self):
3217db96d56Sopenharmony_ci           print(self.recv(8192))
3227db96d56Sopenharmony_ci
3237db96d56Sopenharmony_ci       def writable(self):
3247db96d56Sopenharmony_ci           return (len(self.buffer) > 0)
3257db96d56Sopenharmony_ci
3267db96d56Sopenharmony_ci       def handle_write(self):
3277db96d56Sopenharmony_ci           sent = self.send(self.buffer)
3287db96d56Sopenharmony_ci           self.buffer = self.buffer[sent:]
3297db96d56Sopenharmony_ci
3307db96d56Sopenharmony_ci
3317db96d56Sopenharmony_ci   client = HTTPClient('www.python.org', '/')
3327db96d56Sopenharmony_ci   asyncore.loop()
3337db96d56Sopenharmony_ci
3347db96d56Sopenharmony_ci.. _asyncore-example-2:
3357db96d56Sopenharmony_ci
3367db96d56Sopenharmony_ciasyncore Example basic echo server
3377db96d56Sopenharmony_ci----------------------------------
3387db96d56Sopenharmony_ci
3397db96d56Sopenharmony_ciHere is a basic echo server that uses the :class:`dispatcher` class to accept
3407db96d56Sopenharmony_ciconnections and dispatches the incoming connections to a handler::
3417db96d56Sopenharmony_ci
3427db96d56Sopenharmony_ci    import asyncore
3437db96d56Sopenharmony_ci
3447db96d56Sopenharmony_ci    class EchoHandler(asyncore.dispatcher_with_send):
3457db96d56Sopenharmony_ci
3467db96d56Sopenharmony_ci        def handle_read(self):
3477db96d56Sopenharmony_ci            data = self.recv(8192)
3487db96d56Sopenharmony_ci            if data:
3497db96d56Sopenharmony_ci                self.send(data)
3507db96d56Sopenharmony_ci
3517db96d56Sopenharmony_ci    class EchoServer(asyncore.dispatcher):
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci        def __init__(self, host, port):
3547db96d56Sopenharmony_ci            asyncore.dispatcher.__init__(self)
3557db96d56Sopenharmony_ci            self.create_socket()
3567db96d56Sopenharmony_ci            self.set_reuse_addr()
3577db96d56Sopenharmony_ci            self.bind((host, port))
3587db96d56Sopenharmony_ci            self.listen(5)
3597db96d56Sopenharmony_ci
3607db96d56Sopenharmony_ci        def handle_accepted(self, sock, addr):
3617db96d56Sopenharmony_ci            print('Incoming connection from %s' % repr(addr))
3627db96d56Sopenharmony_ci            handler = EchoHandler(sock)
3637db96d56Sopenharmony_ci
3647db96d56Sopenharmony_ci    server = EchoServer('localhost', 8080)
3657db96d56Sopenharmony_ci    asyncore.loop()
366