tornado.websocket — Bidirectional communication to the browser

Implementation of the WebSocket protocol.

WebSocket允许浏览器和服务器之间的双向通信.

当前,所有主要浏览器的版本均支持WebSocket,尽管仍在使用不支持WebSocket的旧版本(有关详细信息,请参阅http://caniuse.com/websockets ).

此模块实现RFC 6455中定义的WebSocket协议的最终版本. 某些浏览器版本(尤其是Safari 5.x)实现了该协议的较早草案(称为"草稿76"),并且与该模块不兼容.

在版本4.0中更改: Removed support for the draft 76 protocol version.

class tornado.websocket.WebSocketHandler(application: tornado.web.Application, request: tornado.httputil.HTTPServerRequest, **kwargs)[source]

子类创建一个基本的WebSocket处理程序.

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

可以通过覆盖set_default_headersprepare来发送自定义升级响应标头.

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

WebSocket不是标准的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);
};

This script pops up an alert box that says “You said: Hello, world”.

Web浏览器允许任何站点打开与任何其他站点的websocket连接,而不是使用从javascript管理其他网络访问的同源策略. 这可能是令人惊讶的,并且可能是一个潜在的安全漏洞,因此,由于Tornado 4.0 WebSocketHandler要求希望通过覆盖check_origin方法来接收跨域websocket的应用程序(请参见该方法的文档以获取详细信息). 未能建立连接是最可能导致403错误的原因.

当使用带有自签名证书的安全websocket连接( wss:// )时,来自浏览器的连接可能会失败,因为它想要显示"接受此证书"对话框,但无处可显示. 在Websocket连接成功之前,您必须先使用相同的证书访问常规HTML页面以接受它.

如果应用程序设置websocket_ping_interval值非零,则将定期发送ping,如果在websocket_ping_timeout之前未收到响应,则连接将关闭.

大于websocket_max_message_size应用程序设置(默认为10MiB)的消息将不被接受.

在版本4.5中更改:添加了websocket_ping_intervalwebsocket_ping_timeoutwebsocket_max_message_size .

Event handlers

WebSocketHandler.open(*args, **kwargs) → Optional[Awaitable[None]][source]

打开新的WebSocket时调用.

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

open可能是一个协程. 在open返回之前,不会调用on_message .

在5.1版中进行了更改: open可能是一个协程.

WebSocketHandler.on_message(message: Union[str, bytes]) → Optional[Awaitable[None]][source]

处理WebSocket上的传入消息

此方法必须被覆盖.

在版本4.5中更改: on_message可以是协程.

WebSocketHandler.on_close() → None[source]

WebSocket关闭时调用.

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

在版本4.0中更改: Added close_code and close_reason attributes.

WebSocketHandler.select_subprotocol(subprotocols: List[str]) → Optional[str][source]

重写以实现子协议协商.

subprotocols是一个字符串列表,用于标识客户端提出的子协议. 可以重写此方法以返回那些字符串之一来选择它,或者返回None以不选择子协议.

选择子协议失败不会自动中止连接,尽管如果未选择任何建议的子协议,客户端可能会关闭连接.

该列表可能为空,在这种情况下,此方法必须返回None. 即使未提出任何子协议,也始终只精确调用一次此方法,以便可以将此情况告知处理程序.

在版本5.1中进行了更改:以前,此方法使用包含空字符串的列表而不是客户端未提出子协议的列表来调用.

WebSocketHandler.selected_subprotocol

select_subprotocol返回的子协议.

5.1版中的新功能.

WebSocketHandler.on_ping(data: bytes) → None[source]

收到ping帧时调用.

Output

WebSocketHandler.write_message(message: Union[bytes, str, Dict[str, Any]], binary: bool = False) → Future[None][source]

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

该消息可以是字符串,也可以是字典(将被编码为json). 如果binary参数为false,则消息将以utf8的形式发送;否则,将以utf8的形式发送. 在二进制模式下,允许任何字节字符串.

如果连接已经关闭,则引发WebSocketClosedError . 返回可以用于流控制的Future .

在版本3.2中更改:添加了WebSocketClosedError (以前,关闭的连接将引发AttributeError

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

在版本5.0中更改:始终引发WebSocketClosedError . 以前有时可能会引发StreamClosedError .

WebSocketHandler.close(code: int = None, reason: str = None) → None[source]

关闭此Web套接字.

Once the close handshake is successful the socket will be closed.

code可以是数字状态代码,取自RFC 6455第7.4.1节中定义的值. reason可能是有关连接关闭reason的文本消息. 这些值可供客户端使用,但websocket协议不会对其进行解释.

在版本4.0中更改:添加了codereason参数.

Configuration

WebSocketHandler.check_origin(origin: str) → bool[source]

重写以启用对允许替代原点的支持.

origin参数是Origin HTTP标头的值, Origin HTTP标头负责启动此请求. 不发送此标头的客户端不调用此方法. 始终允许此类请求(因为所有实现WebSocket的浏览器都支持此标头,并且非浏览器客户端没有相同的跨站点安全性问题).

应该返回True接受请求,或者返回False拒绝请求. 默认情况下,拒绝源于此主机以外的主机的所有请求.

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

Warning

这是一项重要的安全措施. 在不了解安全隐患的情况下不要禁用它. 特别是,如果您的身份验证是基于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")

版本4.0中的新功能.

WebSocketHandler.get_compression_options() → Optional[Dict[str, Any]][source]

重写以返回连接的压缩选项.

如果此方法返回None(默认值),则将禁用压缩. 如果它返回一个dict(甚至是一个空的dict),它将被启用. dict的内容可用于控制以下压缩选项:

compression_level指定压缩级别.

mem_level指定用于内部压缩状态的内存量.

这些参数在此处详细记录: https : //docs.python.org/3.6/library/zlib.html#zlib.compressobj

4.1版中的新功能.

在版本4.5中进行了更改: Added compression_level and mem_level.

WebSocketHandler.set_nodelay(value: bool) → None[source]

Set the no-delay flag for this stream.

默认情况下,小消息可能会延迟和/或合并以最小化发送的数据包数量. 由于Nagle的算法与TCP延迟的ACK之间的相互作用,有时可能会导致200-500ms的延迟. 要减少此延迟(以可能增加带宽使用为代价),请在建立websocket连接后调用self.set_nodelay(True) .

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

3.1版中的新功能.

Other

WebSocketHandler.ping(data: Union[str, bytes] = b'') → None[source]

将ping帧发送到远端.

data参数允许将少量数据(最多125个字节)作为ping消息的一部分发送. 请注意,并非所有的websocket实现都将此数据公开给应用程序.

考虑使用websocket_ping_interval应用程序设置,而不是手动发送ping.

在版本5.1中更改: data参数现在是可选的.

WebSocketHandler.on_pong(data: bytes) → None[source]

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

exception tornado.websocket.WebSocketClosedError[source]

通过对封闭连接的操作引发.

3.2版中的新功能.

Client-side support

tornado.websocket.websocket_connect(url: Union[str, tornado.httpclient.HTTPRequest], callback: Callable[[Future[WebSocketClientConnection]], None] = None, connect_timeout: float = None, on_message_callback: Callable[[Union[None, str, bytes]], None] = None, compression_options: Dict[str, Any] = None, ping_interval: float = None, ping_timeout: float = None, max_message_size: int = 10485760, subprotocols: List[str] = None) → Awaitable[WebSocketClientConnection][source]

客户端websocket支持.

获取一个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 may be a list of strings specifying proposed subprotocols. subprotocols可以是指定提议的子协议的字符串列表. The selected protocol may be found on the selected_subprotocol attribute of the connection object when the connection is complete. 连接完成后,可以在连接对象的selected_subprotocol属性上找到所选协议.

在版本3.2中更改:还接受HTTPRequest对象代替url.

在版本4.1中进行了更改: Added compression_options and on_message_callback.

在版本4.5中进行了更改:添加了ping_intervalping_timeoutmax_message_size参数,其含义与WebSocketHandler含义相同.

在5.0版中进行了更改: io_loop参数(从4.1版弃用)已被删除.

在版本5.1中更改:添加了subprotocols参数.

class tornado.websocket.WebSocketClientConnection(request: tornado.httpclient.HTTPRequest, on_message_callback: Callable[[Union[None, str, bytes]], None] = None, compression_options: Dict[str, Any] = None, ping_interval: float = None, ping_timeout: float = None, max_message_size: int = 10485760, subprotocols: Optional[List[str]] = [])[source]

WebSocket客户端连接.

此类不应该直接实例化; 请改用websocket_connect函数.

close(code: int = None, reason: str = None) → None[source]

关闭websocket连接.

codereason记录在WebSocketHandler.close下.

3.2版中的新功能.

在版本4.0中更改:添加了codereason参数.

write_message(message: Union[str, bytes], binary: bool = False) → Future[None][source]

将消息发送到WebSocket服务器.

如果流关闭,则引发WebSocketClosedError . 返回可以用于流控制的Future .

在版本5.0中更改:在关闭的流上引发的异常从StreamClosedError更改为WebSocketClosedError .

read_message(callback: Callable[[Future[Union[None, str, bytes]]], None] = None) → Awaitable[Union[None, str, bytes]][source]

从WebSocket服务器读取消息.

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

返回以消息为结果的future,如果连接已关闭,则返回None. 如果给出了回调参数,则准备就绪时将在将来调用它.

ping(data: bytes = b'') → None[source]

将ping帧发送到远端.

data参数允许将少量数据(最多125个字节)作为ping消息的一部分发送. 请注意,并非所有的websocket实现都将此数据公开给应用程序.

考虑对websocket_connect使用ping_interval参数,而不是手动发送ping.

5.1版中的新功能.

property selected_subprotocol

服务器选择的子协议.

5.1版中的新功能.