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