@@ -21,9 +21,10 @@ features:
2121 Socket.IO specification.
2222- Compatible with Python 2.7 and Python 3.3+.
2323- Supports large number of clients even on modest hardware when used with an
24- asynchronous server based on `eventlet <http://eventlet.net/ >`_ or
25- `gevent <http://gevent.org/ >`_. For development and testing, any WSGI
26- complaint multi-threaded server can be used.
24+ asynchronous server based on `asyncio <https://docs.python.org/3/library/asyncio.html >`_,
25+ `eventlet <http://eventlet.net/ >`_ or `gevent <http://gevent.org/ >`_. For
26+ development and testing, any WSGI complaint multi-threaded server can also be
27+ used.
2728- Includes a WSGI middleware that integrates Socket.IO traffic with standard
2829 WSGI applications.
2930- Broadcasting of messages to all connected clients, or to subsets of them
@@ -55,8 +56,45 @@ The Socket.IO server can be installed with pip::
5556
5657 pip install python-socketio
5758
58- The following is a basic example of a Socket.IO server that uses Flask to
59- deploy the client code to the browser::
59+ The following is a basic example of a Socket.IO server that uses the
60+ `aiohttp <http://aiohttp.readthedocs.io/ >`_ framework for asyncio (Python 3.5+
61+ only):
62+
63+ .. code :: python
64+
65+ from aiohttp import web
66+ import socketio
67+
68+ sio = socketio.AsyncServer()
69+ app = web.Application()
70+ sio.attach(app)
71+
72+ async def index (request ):
73+ """ Serve the client-side application."""
74+ with open (' index.html' ) as f:
75+ return web.Response(text = f.read(), content_type = ' text/html' )
76+
77+ @sio.on (' connect' , namespace = ' /chat' )
78+ def connect (sid , environ ):
79+ print (" connect " , sid)
80+
81+ @sio.on (' chat message' , namespace = ' /chat' )
82+ async def message (sid , data ):
83+ print (" message " , data)
84+ await sio.emit(' reply' , room = sid)
85+
86+ @sio.on (' disconnect' , namespace = ' /chat' )
87+ def disconnect (sid ):
88+ print (' disconnect ' , sid)
89+
90+ app.router.add_static(' /static' , ' static' )
91+ app.router.add_get(' /' , index)
92+
93+ if __name__ == ' __main__' :
94+ web.run_app(app)
95+
96+ And below is a similar example, but using Flask and Eventlet. This example is
97+ compatible with Python 2.7 and 3.3+::
6098
6199 import socketio
62100 import eventlet
@@ -107,6 +145,41 @@ them with event handlers. An event is defined simply by a name.
107145When a connection with a client is broken, the ``disconnect `` event is called,
108146allowing the application to perform cleanup.
109147
148+ Server
149+ ------
150+
151+ Socket.IO servers are instances of class :class: `socketio.Server `, which can be
152+ combined with a WSGI compliant application using :class: `socketio.Middleware `::
153+
154+ # create a Socket.IO server
155+ sio = socketio.Server()
156+
157+ # wrap WSGI application with socketio's middleware
158+ app = socketio.Middleware(sio, app)
159+
160+
161+ For asyncio based servers, the :class: `socketio.AsyncServer ` class provides a
162+ coroutine friendly server::
163+
164+ # create a Socket.IO server
165+ sio = socketio.AsyncServer()
166+
167+ # attach server to application
168+ sio.attach(app)
169+
170+ Event handlers for servers are register using the :func: `socketio.Server.on `
171+ method::
172+
173+ @sio.on('my custom event')
174+ def my_custom_event():
175+ pass
176+
177+ For asyncio servers, event handlers can be regular functions or coroutines::
178+
179+ @sio.on('my custom event')
180+ async def my_custom_event():
181+ await sio.emit('my reply')
182+
110183Rooms
111184-----
112185
@@ -232,6 +305,22 @@ that belong to a namespace can be created as methods of a subclass of
232305
233306 sio.register_namespace(MyCustomNamespace('/test'))
234307
308+ For asyncio based severs, namespaces must inherit from
309+ :class: `socketio.AsyncNamespace `, and can define event handlers as regular
310+ methods or coroutines::
311+
312+ class MyCustomNamespace(socketio.AsyncNamespace):
313+ def on_connect(sid, environ):
314+ pass
315+
316+ def on_disconnect(sid):
317+ pass
318+
319+ async def on_my_event(sid, data):
320+ await self.emit('my_response', data)
321+
322+ sio.register_namespace(MyCustomNamespace('/test'))
323+
235324When class-based namespaces are used, any events received by the server are
236325dispatched to a method named as the event name with the ``on_ `` prefix. For
237326example, event ``my_event `` will be handled by a method named ``on_my_event ``.
@@ -241,8 +330,8 @@ class-based namespaces must used characters that are legal in method names.
241330
242331As a convenience to methods defined in a class-based namespace, the namespace
243332instance includes versions of several of the methods in the
244- :class: `socketio.Server ` class that default to the proper namespace when the
245- ``namespace `` argument is not given.
333+ :class: `socketio.Server ` and : class: ` socketio.AsyncServer ` classes that default
334+ to the proper namespace when the ``namespace `` argument is not given.
246335
247336In the case that an event has a handler in a class-based namespace, and also a
248337decorator-based function handler, only the standalone function handler is
@@ -344,6 +433,33 @@ Deployment
344433The following sections describe a variety of deployment strategies for
345434Socket.IO servers.
346435
436+ Aiohttp
437+ ~~~~~~~
438+
439+ `Aiohttp <http://aiohttp.readthedocs.io/ >`_ is a framework with support for HTTP
440+ and WebSocket, based on asyncio. Support for this framework is limited to Python
441+ 3.5 and newer.
442+
443+ Instances of class ``engineio.AsyncServer `` will automatically use aiohttp
444+ for asynchronous operations if the library is installed. To request its use
445+ explicitly, the ``async_mode `` option can be given in the constructor::
446+
447+ sio = socketio.AsyncServer(async_mode='aiohttp')
448+
449+ A server configured for aiohttp must be attached to an existing application::
450+
451+ app = web.Application()
452+ sio.attach(app)
453+
454+ The aiohttp application can define regular routes that will coexist with the
455+ Socket.IO server. A typical pattern is to add routes that serve a client
456+ application and any associated static files.
457+
458+ The aiohttp application is then executed in the usual manner::
459+
460+ if __name__ == '__main__':
461+ web.run_app(app)
462+
347463Eventlet
348464~~~~~~~~
349465
@@ -385,7 +501,7 @@ database drivers are likely to require it.
385501Gevent
386502~~~~~~
387503
388- `Gevent <http://gevent.org >`_ is another asynchronous framework based on
504+ `Gevent <http://gevent.org/ >`_ is another asynchronous framework based on
389505coroutines, very similar to eventlet. An Socket.IO server deployed with
390506gevent has access to the long-polling transport. If project
391507`gevent-websocket <https://bitbucket.org/Jeffrey/gevent-websocket/ >`_ is
@@ -503,8 +619,8 @@ difficult. To deploy a cluster of Socket.IO processes (hosted on one or
503619multiple servers), the following conditions must be met:
504620
505621- Each Socket.IO process must be able to handle multiple requests, either by
506- using eventlet, gevent, or standard threads. Worker processes that only
507- handle one request at a time are not supported.
622+ using asyncio, eventlet, gevent, or standard threads. Worker processes that
623+ only handle one request at a time are not supported.
508624- The load balancer must be configured to always forward requests from a
509625 client to the same worker process. Load balancers call this *sticky
510626 sessions *, or *session affinity *.
@@ -516,17 +632,36 @@ API Reference
516632-------------
517633
518634.. module :: socketio
635+
519636.. autoclass :: Middleware
520637 :members:
638+
521639.. autoclass :: Server
522640 :members:
641+
642+ .. autoclass :: AsyncServer
643+ :members:
644+ :inherited-members:
645+
523646.. autoclass :: Namespace
524647 :members:
648+
649+ .. autoclass :: AsyncNamespace
650+ :members:
651+ :inherited-members:
652+
525653.. autoclass :: BaseManager
526654 :members:
655+
527656.. autoclass :: PubSubManager
528657 :members:
658+
529659.. autoclass :: KombuManager
530660 :members:
661+
531662.. autoclass :: RedisManager
532663 :members:
664+
665+ .. autoclass :: AsyncManager
666+ :members:
667+ :inherited-members:
0 commit comments