Skip to content

Commit 510a6f7

Browse files
committed
Add a FAQ.
Fix #621.
1 parent 7d429b5 commit 510a6f7

File tree

2 files changed

+212
-0
lines changed

2 files changed

+212
-0
lines changed

docs/faq.rst

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
FAQ
2+
===
3+
4+
.. currentmodule:: websockets
5+
6+
.. note::
7+
8+
Many questions asked in :mod:`websockets`' issue tracker are actually
9+
about :mod:`asyncio`. Python's documentation about `developing with
10+
asyncio`_ is a good complement.
11+
12+
.. _developing with asyncio: https://docs.python.org/3/library/asyncio-dev.html
13+
14+
Server side
15+
-----------
16+
17+
Why does the server close the connection after processing one message?
18+
......................................................................
19+
20+
Your connection handler exits after processing one message. Write a loop to
21+
process multiple messages.
22+
23+
For example, if your handler looks like this::
24+
25+
async def handler(websocket, path):
26+
print(websocket.recv())
27+
28+
change it like this::
29+
30+
async def handler(websocket, path):
31+
async for message in websocket:
32+
print(message)
33+
34+
*Don't feel bad if this happens to you — it's the most common question in
35+
websockets' issue tracker :-)*
36+
37+
Why can only one client connect at a time?
38+
..........................................
39+
40+
Your connection handler blocks the event loop. Look for blocking calls.
41+
Any call that may take some time must be asynchronous.
42+
43+
For example, if you have::
44+
45+
async def handler(websocket, path):
46+
time.sleep(1)
47+
48+
change it to::
49+
50+
async def handler(websocket, path):
51+
await asyncio.sleep(1)
52+
53+
This is part of learning asyncio. It isn't specific to websockets.
54+
55+
See also Python's documentation about `running blocking code`_.
56+
57+
.. _running blocking code: https://docs.python.org/3/library/asyncio-dev.html#running-blocking-code
58+
59+
How do I get access HTTP headers, for example cookies?
60+
......................................................
61+
62+
To access HTTP headers during the WebSocket handshake, you can override
63+
:attr:`~server.WebSocketServerProtocol.process_request`::
64+
65+
async def process_request(self, path, request_headers):
66+
cookies = request_header["Cookie"]
67+
68+
See
69+
70+
Once the connection is established, they're available in
71+
:attr:`~protocol.WebSocketServerProtocol.request_headers`::
72+
73+
async def handler(websocket, path):
74+
cookies = websocket.request_headers["Cookie"]
75+
76+
How do I get the IP address of the client connecting to my server?
77+
..................................................................
78+
79+
It's available in :attr:`~protocol.WebSocketCommonProtocol.remote_address`::
80+
81+
async def handler(websocket, path):
82+
remote_ip = websocket.remote_address[0]
83+
84+
How do I set which IP addresses my server listens to?
85+
.....................................................
86+
87+
Look at the ``host`` argument of :meth:`~asyncio.loop.create_server`.
88+
89+
:func:`serve` accepts the same arguments as
90+
:meth:`~asyncio.loop.create_server`.
91+
92+
How do I close a connection properly?
93+
.....................................
94+
95+
websockets takes care of closing the connection when the handler exits.
96+
97+
How do I run a HTTP server and WebSocket server on the same port?
98+
.................................................................
99+
100+
This isn't supported.
101+
102+
Providing a HTTP server is out of scope for websockets. It only aims at
103+
providing a WebSocket server.
104+
105+
There's limited support for returning HTTP responses with the
106+
:attr:`~server.WebSocketServerProtocol.process_request` hook.
107+
If you need more, pick a HTTP server and run it separately.
108+
109+
Client side
110+
-----------
111+
112+
How do I close a connection properly?
113+
.....................................
114+
115+
The easiest is to use :func:`connect` as a context manager::
116+
117+
async with connect(...) as websocket:
118+
...
119+
120+
How do I reconnect automatically when the connection drops?
121+
...........................................................
122+
123+
See `issue 414`_.
124+
125+
.. _issue 414: https://github.com/aaugustin/websockets/issues/414
126+
127+
How do I disable SSL certificate verification?
128+
..............................................
129+
130+
Look at the ``ssl`` argument of :meth:`~asyncio.loop.create_connection`.
131+
132+
:func:`connect` accepts the same arguments as
133+
:meth:`~asyncio.loop.create_connection`.
134+
135+
Architecture
136+
------------
137+
138+
How do I do two things in parallel? How do I integrate with another coroutine?
139+
..............................................................................
140+
141+
You must start two tasks, which the event loop will run concurrently. You can
142+
achieve this with :func:`asyncio.gather` or :func:`asyncio.wait`.
143+
144+
This is also part of learning asyncio and not specific to websockets.
145+
146+
Keep track of the tasks and make sure they terminate or you cancel them when
147+
the connection terminates.
148+
149+
How do I create channels or topics?
150+
...................................
151+
152+
websockets doesn't have built-in publish / subscribe for these use cases.
153+
154+
Depending on the scale of your service, a simple in-memory implementation may
155+
do the job or you may need an external publish / subscribe component.
156+
157+
Are there ``onopen``, ``onmessage``, ``onerror``, and ``onclose`` callbacks?
158+
............................................................................
159+
160+
No, there aren't.
161+
162+
websockets provides high-level, coroutine-based APIs. Compared to callbacks,
163+
coroutines make it easier to manage control flow in concurrent code.
164+
165+
If you prefer callback-based APIs, you should use another library.
166+
167+
Can I use ``websockets`` synchronously, without ``async`` / ``await``?
168+
......................................................................
169+
170+
You can convert every asynchronous call to a synchronous call by wrapping it
171+
in ``asyncio.get_event_loop().run_until_complete(...)``.
172+
173+
If this turns out to be impractical, you should use another library.
174+
175+
Miscellaneous
176+
-------------
177+
178+
How do I set a timeout on ``recv()``?
179+
.....................................
180+
181+
Use :func:`~asyncio.wait_for`::
182+
183+
await asyncio.wait_for(websocket.recv(), timeout=10)
184+
185+
This technique works for most APIs, except for asynchronous context managers.
186+
See `issue 574`_.
187+
188+
.. _issue 574: https://github.com/aaugustin/websockets/issues/574
189+
190+
How do I keep idle connections open?
191+
....................................
192+
193+
websockets sends pings at 20 seconds intervals to keep the connection open.
194+
195+
In closes the connection if it doesn't get a pong within 20 seconds.
196+
197+
You can adjust this behavior with ``ping_interval`` and ``ping_timeout``.
198+
199+
How do I respond to pings?
200+
..........................
201+
202+
websockets takes care of responding to pings with pongs.
203+
204+
Is there a Python 2 version?
205+
............................
206+
207+
No, there isn't.
208+
209+
websockets builds upon asyncio which requires Python 3.
210+
211+

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ If you're new to ``websockets``, this is the place to start.
4949
:maxdepth: 2
5050

5151
intro
52+
faq
5253

5354
How-to guides
5455
-------------

0 commit comments

Comments
 (0)