1FAQ
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
14Server side
15-----------
16
17Why does the server close the connection after processing one message?
18......................................................................
19
20Your connection handler exits after processing one message. Write a loop to
21process multiple messages.
22
23For example, if your handler looks like this::
24
25    async def handler(websocket, path):
26        print(websocket.recv())
27
28change 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
35websockets' issue tracker :-)*
36
37Why can only one client connect at a time?
38..........................................
39
40Your connection handler blocks the event loop. Look for blocking calls.
41Any call that may take some time must be asynchronous.
42
43For example, if you have::
44
45    async def handler(websocket, path):
46        time.sleep(1)
47
48change it to::
49
50    async def handler(websocket, path):
51        await asyncio.sleep(1)
52
53This is part of learning asyncio. It isn't specific to websockets.
54
55See 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
59How do I get access HTTP headers, for example cookies?
60......................................................
61
62To 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
68See
69
70Once 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
76How do I get the IP address of the client connecting to my server?
77..................................................................
78
79It's available in :attr:`~protocol.WebSocketCommonProtocol.remote_address`::
80
81    async def handler(websocket, path):
82        remote_ip = websocket.remote_address[0]
83
84How do I set which IP addresses my server listens to?
85.....................................................
86
87Look 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
92How do I close a connection properly?
93.....................................
94
95websockets takes care of closing the connection when the handler exits.
96
97How do I run a HTTP server and WebSocket server on the same port?
98.................................................................
99
100This isn't supported.
101
102Providing a HTTP server is out of scope for websockets. It only aims at
103providing a WebSocket server.
104
105There's limited support for returning HTTP responses with the
106:attr:`~server.WebSocketServerProtocol.process_request` hook.
107If you need more, pick a HTTP server and run it separately.
108
109Client side
110-----------
111
112How do I close a connection properly?
113.....................................
114
115The easiest is to use :func:`connect` as a context manager::
116
117    async with connect(...) as websocket:
118        ...
119
120How do I reconnect automatically when the connection drops?
121...........................................................
122
123See `issue 414`_.
124
125.. _issue 414: https://github.com/aaugustin/websockets/issues/414
126
127How do I disable TLS/SSL certificate verification?
128..................................................
129
130Look 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
135Both sides
136----------
137
138How do I do two things in parallel? How do I integrate with another coroutine?
139..............................................................................
140
141You must start two tasks, which the event loop will run concurrently. You can
142achieve this with :func:`asyncio.gather` or :func:`asyncio.wait`.
143
144This is also part of learning asyncio and not specific to websockets.
145
146Keep track of the tasks and make sure they terminate or you cancel them when
147the connection terminates.
148
149How do I create channels or topics?
150...................................
151
152websockets doesn't have built-in publish / subscribe for these use cases.
153
154Depending on the scale of your service, a simple in-memory implementation may
155do the job or you may need an external publish / subscribe component.
156
157What does ``ConnectionClosedError: code = 1006`` mean?
158......................................................
159
160If you're seeing this traceback in the logs of a server:
161
162.. code-block:: pytb
163
164    Error in connection handler
165    Traceback (most recent call last):
166      ...
167    asyncio.streams.IncompleteReadError: 0 bytes read on a total of 2 expected bytes
168
169    The above exception was the direct cause of the following exception:
170
171    Traceback (most recent call last):
172      ...
173    websockets.exceptions.ConnectionClosedError: code = 1006 (connection closed abnormally [internal]), no reason
174
175or if a client crashes with this traceback:
176
177.. code-block:: pytb
178
179    Traceback (most recent call last):
180      ...
181    ConnectionResetError: [Errno 54] Connection reset by peer
182
183    The above exception was the direct cause of the following exception:
184
185    Traceback (most recent call last):
186      ...
187    websockets.exceptions.ConnectionClosedError: code = 1006 (connection closed abnormally [internal]), no reason
188
189it means that the TCP connection was lost. As a consequence, the WebSocket
190connection was closed without receiving a close frame, which is abnormal.
191
192You can catch and handle :exc:`~exceptions.ConnectionClosed` to prevent it
193from being logged.
194
195There are several reasons why long-lived connections may be lost:
196
197* End-user devices tend to lose network connectivity often and unpredictably
198  because they can move out of wireless network coverage, get unplugged from
199  a wired network, enter airplane mode, be put to sleep, etc.
200* HTTP load balancers or proxies that aren't configured for long-lived
201  connections may terminate connections after a short amount of time, usually
202  30 seconds.
203
204If you're facing a reproducible issue, :ref:`enable debug logs <debugging>` to
205see when and how connections are closed.
206
207Are there ``onopen``, ``onmessage``, ``onerror``, and ``onclose`` callbacks?
208............................................................................
209
210No, there aren't.
211
212websockets provides high-level, coroutine-based APIs. Compared to callbacks,
213coroutines make it easier to manage control flow in concurrent code.
214
215If you prefer callback-based APIs, you should use another library.
216
217Can I use ``websockets`` synchronously, without ``async`` / ``await``?
218......................................................................
219
220You can convert every asynchronous call to a synchronous call by wrapping it
221in ``asyncio.get_event_loop().run_until_complete(...)``.
222
223If this turns out to be impractical, you should use another library.
224
225Miscellaneous
226-------------
227
228How do I set a timeout on ``recv()``?
229.....................................
230
231Use :func:`~asyncio.wait_for`::
232
233    await asyncio.wait_for(websocket.recv(), timeout=10)
234
235This technique works for most APIs, except for asynchronous context managers.
236See `issue 574`_.
237
238.. _issue 574: https://github.com/aaugustin/websockets/issues/574
239
240How do I keep idle connections open?
241....................................
242
243websockets sends pings at 20 seconds intervals to keep the connection open.
244
245In closes the connection if it doesn't get a pong within 20 seconds.
246
247You can adjust this behavior with ``ping_interval`` and ``ping_timeout``.
248
249How do I respond to pings?
250..........................
251
252websockets takes care of responding to pings with pongs.
253
254Is there a Python 2 version?
255............................
256
257No, there isn't.
258
259websockets builds upon asyncio which requires Python 3.
260
261
262