Tornado中使用Websocket

Websocket在线测试工具

WebSocket – 维基百科,自由的百科全书

利用websocket实现推送

支持异步的一个库websockets

Python Web学习笔记之WebSocket 通信过程与实现

长轮询的方式:

image-20191102214850668

使用Websocket方式:

image-20191102214912454

Websocket方式同样支持客户端主动发送数据

image-20191102214948905

连接可能因为许多你无法控制的原因而意外关闭。任何Web应用程序都应该能够很好地处理间歇连接性并正确地恢复。然而,有些连接关闭的原因是可以且应当避免的。可以避免的常见连接丢失原因是TCP级别的空闲,这会影响WebSocket连接。

说明 : 因为WebSocket连接处于TCP连接的上层,发生在TCP级别的连接问题会影响WebSocket连接。

在客户端和WebSocket服务器之间的全双工连接中,有时候连接上可能没有数据流。在这个时候,网络中介可能中止连接。具体地说,不知道“始终打开”连接的网络组件有时候会关闭不活跃的TCP连接,从而关闭WebSocket连接。例如,代理服务器和家庭路由器有时候会关闭它们认为是空闲的连接。WebSocket协议支持用于连接健康检查和保持连接打开状态的pingpong

使用WebSocket pingpong能够保持连接打开,为数据流动做好准备。pingpong可以从打开的WebSocket连接的任一端发起。WebSocket协议支持客户端发起和服务器发起的ping和pong。浏览器或服务器(也可以是两者)都可以在合适的时间间隔内发起pingpong,保持连接活跃。注意,我们说的是浏览器而不是WebSocket客户端,WebSocket API目前不支持客户端发起的pingpong。虽然浏览器可能根据自己的持续性和健康检查策略发起pingpong,但大部分pingpong是服务器发起的;WebSocket客户端可以用pong响应ping。浏览器和服务器也可以在没有接收ping的情况下发出pong,这为你提供了保持连接活跃时的灵活性。你所使用的时间间隔根据应用程序的受众和通过WebSocket连接的数据流速而定。保守地说,每30秒发送一个pong应该能够保持大部分连接的活跃性,但是更低的频率能够节约带宽和服务器资源。

看下源码:

1
2
3
4
5
6
7
8
9
class EchoWebSocket(tornado.websocket.WebSocketHandler):
def open(self):
print("WebSocket opened")

def on_message(self, message):
self.write_message(u"You said: " + message)

def on_close(self):
print("WebSocket closed")

对应的js源码:

1
2
3
4
5
6
7
var ws = new WebSocket("ws://localhost:8888/websocket");
ws.onopen = function() {
ws.send("Hello, world");
};
ws.onmessage = function (evt) {
alert(evt.data);
};

我们看下源码中值得注意的

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
def open(self, *args: str, **kwargs: str) -> Optional[Awaitable[None]]:
"""Invoked when a new WebSocket is opened.

The arguments to `open` are extracted from the `tornado.web.URLSpec`
regular expression, just like the arguments to
`tornado.web.RequestHandler.get`.

`open` may be a coroutine. `on_message` will not be called until
`open` has returned.

.. versionchanged:: 5.1
# 证明这个函数可以被继承之后写成一个协程函数
``open`` may be a coroutine.
"""
pass

def on_message(self, message: Union[str, bytes]) -> Optional[Awaitable[None]]:
"""Handle incoming messages on the WebSocket

This method must be overridden.

.. versionchanged:: 4.5
# 证明这个函数可以被继承之后写成一个协程函数
``on_message`` can be a coroutine.
"""
raise NotImplementedError

因此我们可以将openon_message写成协程的方式

1
2
3
4
5
6
7
8
async def open(self):
"""连接成功"""
pass


async def on_message(self, data):
"""收到客户端的消息"""
pass

仅仅这些不够 我们下面我们看下如何支持多服务端的情况

知识就是财富
如果您觉得文章对您有帮助, 欢迎请我喝杯水!