Skip to main content

tornado.websocket —与浏览器的双向通信

实现WebSocket协议。

WebSockets 允许浏览器和服务器之间的双向通信。

WebSockets在所有主要浏览器的当前版本中受支持,虽然不支持WebSockets的旧版本仍在使用(有关详细信息,请参阅 http://caniuse.com/websockets)。

此模块实现 RFC 6455 中定义的WebSocket协议的最终版本。某些浏览器版本(特别是Safari 5.x)实现了协议的早期草案(称为“草案76”),与本模块不兼容。

在 4.0 版更改: 删除了对76号草案协议版本的支持。

class tornado.websocket.WebSocketHandler(application, request, **kwargs)[源代码]

Subclass这个类创建一个基本的WebSocket处理程序。

覆盖 on_message 以处理传入的消息,并使用 write_message 向客户端发送消息。您还可以覆盖 openon_close 以处理打开和关闭的连接。

有关JavaScript界面的详细信息,请参阅 http://dev.w3.org/html5/websockets/。协议在 http://tools.ietf.org/html/rfc6455 指定。

这里是一个示例WebSocket处理程序,回传所有接收的消息回客户端:

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")

WebSockets不是标准的HTTP连接。 “握手”是HTTP,但在握手之后,协议是基于消息的。因此,大多数Tornado HTTP设施在此类型的处理程序中不可用。唯一可用的通信方法是 write_message()ping()close()。同样,你的请求处理程序类应该实现 open() 方法,而不是 get()post()

如果将上面的处理程序映射到应用程序中的 /websocket,您可以使用JavaScript调用它:

var ws = new WebSocket("ws://localhost:8888/websocket");
ws.onopen = function() {
   ws.send("Hello, world");
};
ws.onmessage = function (evt) {
   alert(evt.data);
};

这个脚本弹出一个警告框,说“你说:你好,世界”。

Web浏览器允许任何站点打开到任何其他WebSocket连接,而不是使用来自javascript的其他网络访问的同源策略。这可能是令人惊讶的,并且是一个潜在的安全漏洞,所以自从Tornado 4.0 WebSocketHandler 需要应用程序希望接收跨源WebSocket通过重写 check_origin 方法(详细信息请参阅该方法的文档)。否则,在进行websocket连接时最有可能是403错误的原因。

当使用带有自签名证书的安全websocket连接(wss://)时,来自浏览器的连接可能会失败,因为它想显示“接受此证书”对话框,但没有地方显示它。您必须首先访问常规HTML页面,使用相同的证书接受它,然后websocket连接才能成功。

事件处理程序

WebSocketHandler.open(*args, **kwargs)[源代码]

在打开新WebSocket时调用。

open 的参数从 tornado.web.URLSpec 正则表达式中提取,就像 tornado.web.RequestHandler.get 的参数一样。

WebSocketHandler.on_message(message)[源代码]

处理WebSocket上的传入消息

必须覆盖此方法。

WebSocketHandler.on_close()[源代码]

当WebSocket关闭时调用。

如果连接完全关闭并提供了状态代码或原因短语,则这些值将作为属性 self.close_codeself.close_reason 提供。

在 4.0 版更改: 添加了 close_codeclose_reason 属性。

WebSocketHandler.select_subprotocol(subprotocols)[源代码]

当新的WebSocket请求特定的子协议时调用。

subprotocols 是标识客户端建议的子协议的字符串列表。可以覆盖此方法以返回其中一个字符串来选择它,或者 None 不选择子协议。未能选择子协议不会自动中止连接,尽管客户端可能会在没有选择其建议的子协议的情况下关闭连接。

输出

WebSocketHandler.write_message(message, binary=False)[源代码]

将给定消息发送到此Web套接字的客户端。

消息可以是字符串或dict(将被编码为json)。如果 binary 参数为假,则消息将作为utf8发送;在二进制模式下允许任何字节字符串。

如果连接已关闭,则提高 WebSocketClosedError

在 3.2 版更改: 添加了 WebSocketClosedError (以前一个关闭的连接会产生一个 AttributeError

在 4.3 版更改: 返回可用于流控制的 Future

WebSocketHandler.close(code=None, reason=None)[源代码]

关闭此Web套接字。

一旦关闭握手成功,套接字将关闭。

code 可以是取自 RFC 6455第7.4.1节 中定义的值的数字状态代码。 reason 可以是关于为什么连接正在关闭的文本消息。这些值对客户端可用,但不以其他方式由websocket协议解释。

在 4.0 版更改: 添加了 codereason 参数。

组态

WebSocketHandler.check_origin(origin)[源代码]

覆盖以启用支持允许备用来源。

origin 参数是 Origin HTTP标头的值,该标头是负责启动此请求的网址。对于不发送此头的客户端,不调用此方法;这样的请求总是允许的(因为实现WebSockets的所有浏览器都支持这个头,而非浏览器客户端没有相同的跨站点安全问题)。

应返回True以接受请求或False拒绝它。默认情况下,拒绝主机上除了此主机之外的所有请求。

这是一种针对浏览器的跨站点脚本攻击的安全保护,因为允许WebSockets绕过通常的同源策略,并且不使用CORS头。

要接受所有跨源流量(这是Tornado 4.0之前的默认流量),只需重写此方法始终返回true:

def check_origin(self, origin):
    return True

要允许来自您网站的任何子域的连接,您可以执行类似操作:

def check_origin(self, origin):
    parsed_origin = urllib.parse.urlparse(origin)
    return parsed_origin.netloc.endswith(".mydomain.com")

4.0 新版功能.

WebSocketHandler.get_compression_options()[源代码]

覆盖以返回连接的压缩选项。

如果此方法返回None(默认值),将禁用压缩。如果它返回一个dict(甚至一个空的),它将被启用。 dict的内容可以用于控制压缩的存储器和CPU使用,但是目前没有实现这样的选项。

4.1 新版功能.

WebSocketHandler.set_nodelay(value)[源代码]

为此流设置无延迟标志。

默认情况下,小消息可以被延迟和/或组合以最小化发送的分组的数目。由于Nagle的算法和TCP延迟的ACK之间的交互,这有时可能导致200-500ms的延迟。为了减少此延迟(以可能增加带宽使用为代价),一旦websocket连接建立,调用 self.set_nodelay(True)

有关其他详细信息,请参阅 BaseIOStream.set_nodelay

3.1 新版功能.

其他

WebSocketHandler.ping(data)[源代码]

将ping帧发送到远程端。

WebSocketHandler.on_pong(data)[源代码]

在接收到对ping帧的响应时调用。

exception tornado.websocket.WebSocketClosedError[源代码]

在闭合连接上由操作引发。

3.2 新版功能.

客户端支持

tornado.websocket.websocket_connect(url, io_loop=None, callback=None, connect_timeout=None, on_message_callback=None, compression_options=None)[源代码]

客户端websocket支持。

获取一个URL并返回一个结果为 WebSocketClientConnection 的Future。

compression_options 以与 WebSocketHandler.get_compression_options 的返回值相同的方式解释。

该连接支持两种操作方式。在协同程序风格中,应用程序通常在循环中调用 read_message:

conn = yield websocket_connect(url)
while True:
    msg = yield conn.read_message()
    if msg is None: break
    # Do something with msg

在回调样式中,将 on_message_callback 传递给 websocket_connect。在两种样式中,None 的消息表示连接已关闭。

在 3.2 版更改: 也接受 HTTPRequest 对象代替网址。

在 4.1 版更改: 添加了 compression_optionson_message_callbackio_loop 参数已弃用。

class tornado.websocket.WebSocketClientConnection(io_loop, request, on_message_callback=None, compression_options=None)[源代码]

WebSocket客户端连接。

这个类不应该直接实例化;请改用 websocket_connect 函数。

close(code=None, reason=None)[源代码]

关闭websocket连接。

codereason 记录在 WebSocketHandler.close 下。

3.2 新版功能.

在 4.0 版更改: 添加了 codereason 参数。

write_message(message, binary=False)[源代码]

向WebSocket服务器发送消息。

read_message(callback=None)[源代码]

从WebSocket服务器读取消息。

如果在WebSocket初始化时指定了on_message_callback,则此函数永远不会返回消息

返回结果为消息的未来,如果连接关闭,则返回None。如果给出回调参数,它将在未来就绪时调用。