WebSocket 协议的实现,WebSockets 允许浏览器和服务器之间的双向通信。
所有主流浏览器的当前版本都支持 WebSockets,尽管不支持 WebSockets 的旧版本仍在使用
该模块实现了 RFC 6455 中定义的 WebSocket 协议的最终版本。某些浏览器版本(尤其是 Safari 5.x)实现了该协议的早期草案(称为“draft 76”)并且与该模块不兼容。
在 4.0 版更改: 删除了对草案 76 协议版本的支持。
子类化此类以创建基本的 WebSocket 处理程序。
重写 on_message来处理传入的消息,并使用 write_message将消息发送到客户端。 您还可以覆盖 open和 on_close来处理打开和关闭的连接。
可以通过覆盖 set_default_headers或 prepare来发送自定义升级响应表头。
这是一个示例 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 连接。WebSocket只是使用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);
}; 这个脚本会弹出一个警告框,上面写着“You said:hello,world”。
Web 浏览器允许任何站点打开与任何其他站点的 websocket 连接,而不是使用同源策略来管理来自 JavaScript 的其他网络访问。 这可能令人惊讶并且是一个潜在的安全漏洞,因此由于 Tornado 4.0 WebSocketHandler要求希望接收跨域 websocket 的应用程序通过覆盖 check_origin方法来选择加入。 不这样做是建立 websocket 连接时最可能导致 403 错误的原因。
当使用带有自签名证书的安全 websocket 连接 (wss://) 时,来自浏览器的连接可能会失败,因为它想要显示“接受此证书”对话框但无处显示。 在 websocket 连接成功之前,您必须首先使用相同的证书访问常规 HTML 页面以接受它。
如果应用程序设置 websocket_ping_interval的值为非零值,则会定期发送 ping,如果在 websocket_ping_timeout之前没有收到响应,则连接将关闭。
大于 websocket_max_message_size应用程序设置(默认 10MiB)的消息将不被接受。
在 4.5 版更改:添加了 websocket_ping_interval、websocket_ping_timeout和 websocket_max_message_size。
打开新的 WebSocket 时调用。
open的参数是从tornado.web.URLSpec正则表达式中提取的,就像tornado.web.RequestHandler.get的参数一样。
open可能是一个协程。 在 open返回之前不会调用 on_message。
在 5.1 版更改: open可能是一个协程。
处理 WebSocket 上的传入消息
必须重写此方法。
在 4.5 版更改: on_message可以是协程。
当 WebSocket 关闭时调用。
如果连接完全关闭并且提供了状态代码或原因短语,则这些值将作为属性用于 self.close_code 和 self.close_reason
在 4.0 版更改: 添加了 close_code和 close_reason属性。
重写以实现子协议协商。
subprotocols是标识客户端提出的子协议的字符串列表。 可以重写此方法以返回其中一个字符串以选择它,或者返回 None以不选择子协议。
未能选择子协议不会自动中止连接,尽管如果没有选择任何建议的子协议,客户端可能会关闭连接。
列表可能为空,在这种情况下,此方法必须返回 None。 即使没有提出子协议,该方法也总是只调用一次,以便可以将这一事实告知处理程序。
在 5.1 版更改: 以前,如果客户端没有提出子协议,则使用包含空字符串而不是空列表的列表调用此方法。
select_subprotocol返回的子协议。
5.1 版中的新功能。
在收到 ping 帧时调用。
将给定消息发送到此 Web Socket 的客户端。
消息可以是字符串或字典(将被编码为 json)。 如果 binary参数为 false,则消息将作为 utf8 发送; 在二进制模式下,任何字节串都是允许的。
如果连接已经关闭,则引发 WebSocketClosedError。 返回可用于流量控制的 Future。
在 3.2 版更改:添加了 WebSocketClosedError(以前关闭的连接会引发 AttributeError)
在 4.3 版更改: 返回可用于流量控制的 Future。
在 5.0 版更改: 持续引发 WebSocketClosedError。 以前有时会引发 StreamClosedError。
关闭此 Web Socket。
一旦关闭握手成功,套接字将被关闭。
code可以是数字状态代码,取自 RFC 6455 第 7.4.1 节中定义的值。reason可能是关于连接关闭原因的文本消息。 这些值可供客户端使用,但不会被 websocket 协议解释。
在 4.0 版更改: 添加了code和reason参数。
覆盖以启用对允许备用来源的支持。
origin参数是 OriginHTTP 表头的值,即负责发起此请求的 url。 不发送此表头的客户端不会调用此方法; 这样的请求总是被允许的(因为所有实现 WebSockets 的浏览器都支持这个表头,并且非浏览器客户端没有相同的跨站点安全问题)。
应该返回 True来接受请求或 False来拒绝它。 默认情况下,拒绝所有来自主机以外的主机的请求。
这是针对浏览器上的跨站点脚本攻击的安全保护,因为允许 WebSocket 绕过通常的同源策略并且不使用 CORS 表头。
注意:这是一项重要的安全措施;不要在不了解安全隐患的情况下禁用它。 特别是,如果您的身份验证是基于 cookie 的,您要么限制 check_origin()允许的来源,要么为 websocket 连接实现类似 XSRF 的保护。
要接受所有跨域流量(这是 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")
覆盖以返回连接的压缩选项。
如果此方法返回 None(默认值),压缩将被禁用。 如果它返回一个 dict(甚至是一个空的),它将被启用。 dict 的内容可用于控制以下压缩选项:
compression_level指定压缩级别。
mem_level指定用于内部压缩状态的内存量。
为此流设置无延迟标志。
默认情况下,小消息可能会被延迟组合以最小化发送的数据包数量。 由于 Nagle 的算法和 TCP 延迟 ACK 之间的交互,这有时会导致 200-500 毫秒的延迟。 要减少此延迟(以可能增加带宽使用为代价),请在建立 websocket 连接后调用 self.set_nodelay(True)。
向远端发送 ping 帧。
data 参数允许作为 ping 消息的一部分发送少量数据(最多 125 个字节)。 请注意,并非所有 websocket 实现都会将此数据公开给应用程序。
考虑使用 websocket_ping_interval应用程序设置,而不是手动发送 ping。
在 5.1 版更改: data 参数现在是可选的。
在收到对 ping 帧的响应时调用。
由关闭连接上的操作引发。
接受一个 url 并返回一个 Future,其结果是一个 WebSocketClientConnection。
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 消息表示连接已关闭。
subprotocols可以是指定提议的子协议的字符串列表。 当连接完成时,可以在连接对象的 selected_subprotocol属性上找到所选协议。
在 3.2 版更改: 也接受 HTTPRequest对象代替 url。
在 4.1 版更改:添加了 compression_options和 on_message_callback。
在 4.5 版更改:添加了 ping_interval、ping_timeout和 max_message_size参数,它们与 WebSocketHandler中的含义相同。
在 5.0 版中更改: io_loop参数(自 4.1 版以来已弃用)已被删除。
在 5.1 版更改: 添加了 subprotocols参数。
WebSocket 客户端连接。
这个类不应该直接实例化; 请改用 websocket_connect 函数。
关闭 websocket 连接。
code和reason记录在 WebSocketHandler.close 下。
向 WebSocket 服务器发送消息。
如果流已关闭,则引发 WebSocketClosedError。 返回可用于流量控制的 Future。
在 5.0 版更改:在关闭的流上引发的异常从 StreamClosedError更改为 WebSocketClosedError。
从 WebSocket 服务器读取消息。
如果在 WebSocket 初始化时指定了 on_message_callback,则此函数将永远不会返回消息
返回结果为future的消息,如果连接已关闭,则返回 None。 如果给定了回调参数,它将在准备好时与future一起调用。
向远端发送 ping 帧。
data参数允许作为 ping 消息的一部分发送少量数据(最多 125 个字节)。 请注意,并非所有 websocket 实现都会将此数据公开给应用程序。
考虑对 websocket_connect使用 ping_interval参数,而不是手动发送 ping。
服务器选择的子协议