@@ -40,21 +40,24 @@ It loops through these steps:
40
40
If the Pong frame isn't received, websockets considers the connection broken and
41
41
closes it.
42
42
43
- This mechanism serves two purposes:
43
+ This mechanism serves three purposes:
44
44
45
45
1. It creates a trickle of traffic so that the TCP connection isn't idle and
46
46
network infrastructure along the path keeps it open ("keepalive").
47
47
2. It detects if the connection drops or becomes so slow that it's unusable in
48
48
practice ("heartbeat"). In that case, it terminates the connection and your
49
49
application gets a :exc: `~exceptions.ConnectionClosed ` exception.
50
+ 3. It measures the :attr: `~asyncio.connection.Connection.latency ` of the
51
+ connection. The time between sending a Ping frame and receiving a matching
52
+ Pong frame approximates the round-trip time.
50
53
51
54
Timings are configurable with the ``ping_interval `` and ``ping_timeout ``
52
55
arguments of :func: `~asyncio.client.connect ` and :func: `~asyncio.server.serve `.
53
56
Shorter values will detect connection drops faster but they will increase
54
57
network traffic and they will be more sensitive to latency.
55
58
56
59
Setting ``ping_interval `` to :obj: `None ` disables the whole keepalive and
57
- heartbeat mechanism.
60
+ heartbeat mechanism, including measurement of latency .
58
61
59
62
Setting ``ping_timeout `` to :obj: `None ` disables only timeouts. This enables
60
63
keepalive, to keep idle connections open, and disables heartbeat, to support large
@@ -85,9 +88,23 @@ Unfortunately, the WebSocket API in browsers doesn't expose the native Ping and
85
88
Pong functionality in the WebSocket protocol. You have to roll your own in the
86
89
application layer.
87
90
91
+ Read this `blog post <https://making.close.com/posts/reliable-websockets/ >`_ for
92
+ a complete walk-through of this issue.
93
+
88
94
Latency issues
89
95
--------------
90
96
97
+ The :attr: `~asyncio.connection.Connection.latency ` attribute stores latency
98
+ measured during the last exchange of Ping and Pong frames::
99
+
100
+ latency = websocket.latency
101
+
102
+ Alternatively, you can measure the latency at any time by calling
103
+ :attr: `~asyncio.connection.Connection.ping ` and awaiting its result::
104
+
105
+ pong_waiter = await websocket.ping()
106
+ latency = await pong_waiter
107
+
91
108
Latency between a client and a server may increase for two reasons:
92
109
93
110
* Network connectivity is poor. When network packets are lost, TCP attempts to
@@ -97,7 +114,7 @@ Latency between a client and a server may increase for two reasons:
97
114
98
115
* Traffic is high. For example, if a client sends messages on the connection
99
116
faster than a server can process them, this manifests as latency as well,
100
- because data is waiting in flight, mostly in OS buffers.
117
+ because data is waiting in :doc: ` buffers < memory >` .
101
118
102
119
If the server is more than 20 seconds behind, it doesn't see the Pong before
103
120
the default timeout elapses. As a consequence, it closes the connection.
@@ -109,8 +126,3 @@ Latency between a client and a server may increase for two reasons:
109
126
110
127
The same reasoning applies to situations where the server sends more traffic
111
128
than the client can accept.
112
-
113
- The latency measured during the last exchange of Ping and Pong frames is
114
- available in the :attr: `~asyncio.connection.Connection.latency ` attribute.
115
- Alternatively, you can measure the latency at any time with the
116
- :attr: `~asyncio.connection.Connection.ping ` method.
0 commit comments