1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
Both sides
==========
.. currentmodule:: websockets.asyncio.connection
What does ``ConnectionClosedError: no close frame received or sent`` mean?
--------------------------------------------------------------------------
If you're seeing this traceback in the logs of a server:
.. code-block:: pytb
connection handler failed
Traceback (most recent call last):
...
websockets.exceptions.ConnectionClosedError: no close frame received or sent
or if a client crashes with this traceback:
.. code-block:: pytb
Traceback (most recent call last):
...
websockets.exceptions.ConnectionClosedError: no close frame received or sent
it means that the TCP connection was lost. As a consequence, the WebSocket
connection was closed without receiving and sending a close frame, which is
abnormal.
You can catch and handle :exc:`~websockets.exceptions.ConnectionClosed` to
prevent it from being logged.
There are several reasons why long-lived connections may be lost:
* End-user devices tend to lose network connectivity often and unpredictably
because they can move out of wireless network coverage, get unplugged from
a wired network, enter airplane mode, be put to sleep, etc.
* HTTP load balancers or proxies that aren't configured for long-lived
connections may terminate connections after a short amount of time, usually
30 seconds, despite websockets' keepalive mechanism.
If you're facing a reproducible issue, :doc:`enable debug logs
<../howto/debugging>` to see when and how connections are closed.
What does ``ConnectionClosedError: sent 1011 (internal error) keepalive ping timeout; no close frame received`` mean?
---------------------------------------------------------------------------------------------------------------------
If you're seeing this traceback in the logs of a server:
.. code-block:: pytb
connection handler failed
Traceback (most recent call last):
...
websockets.exceptions.ConnectionClosedError: sent 1011 (internal error) keepalive ping timeout; no close frame received
or if a client crashes with this traceback:
.. code-block:: pytb
Traceback (most recent call last):
...
websockets.exceptions.ConnectionClosedError: sent 1011 (internal error) keepalive ping timeout; no close frame received
it means that the WebSocket connection suffered from excessive latency and was
closed after reaching the timeout of websockets' keepalive mechanism.
You can catch and handle :exc:`~websockets.exceptions.ConnectionClosed` to
prevent it from being logged.
There are two main reasons why latency may increase:
* Poor network connectivity.
* More traffic than the recipient can handle.
See the discussion of :doc:`keepalive <../topics/keepalive>` for details.
If websockets' default timeout of 20 seconds is too short for your use case,
you can adjust it with the ``ping_timeout`` argument.
How do I set a timeout on :meth:`~Connection.recv`?
---------------------------------------------------
On Python ≥ 3.11, use :func:`asyncio.timeout`::
async with asyncio.timeout(timeout=10):
message = await websocket.recv()
On older versions of Python, use :func:`asyncio.wait_for`::
message = await asyncio.wait_for(websocket.recv(), timeout=10)
This technique works for most APIs. When it doesn't, for example with
asynchronous context managers, websockets provides an ``open_timeout`` argument.
How can I pass arguments to a custom connection subclass?
---------------------------------------------------------
You can bind additional arguments to the connection factory with
:func:`functools.partial`::
import asyncio
import functools
from websockets.asyncio.server import ServerConnection, serve
class MyServerConnection(ServerConnection):
def __init__(self, *args, extra_argument=None, **kwargs):
super().__init__(*args, **kwargs)
# do something with extra_argument
create_connection = functools.partial(ServerConnection, extra_argument=42)
async with serve(..., create_connection=create_connection):
...
This example was for a server. The same pattern applies on a client.
How do I keep idle connections open?
------------------------------------
websockets sends pings at 20 seconds intervals to keep the connection open.
It closes the connection if it doesn't get a pong within 20 seconds.
You can adjust this behavior with ``ping_interval`` and ``ping_timeout``.
See :doc:`../topics/keepalive` for details.
How do I respond to pings?
--------------------------
If you are referring to Ping_ and Pong_ frames defined in the WebSocket
protocol, don't bother, because websockets handles them for you.
.. _Ping: https://datatracker.ietf.org/doc/html/rfc6455.html#section-5.5.2
.. _Pong: https://datatracker.ietf.org/doc/html/rfc6455.html#section-5.5.3
If you are connecting to a server that defines its own heartbeat at the
application level, then you need to build that logic into your application.
|