SockJS 的目标是让应用程序使用 WebSocket API,但在运行时必要时可退回到非 WebSocket 替代方案,而不需要改变应用程序代码。
SockJS 由以下部分组成:
- 以可执行的 叙述式测试 形式定义的 SockJS 协议。
- SockJS 的 JavaScript 客户端 — 一个用于浏览器的客户端库。
- SockJS 服务器实现,包括 Spring 框架 spring-websocket 模块中的一个。
- spring-websocket 模块中的一个 SockJS Java 客户端(自 4.1 版)。
SockJS 是为在浏览器中使用而设计的。它使用各种技术来支持各种浏览器版本。关于 SockJS 传输类型和浏览器的完整列表,请参阅 SockJS 客户端页面。传输分为三个大类。WebSocket、HTTP Streaming 和 HTTP Long Polling。关于这些类别的概述,请参阅这篇博文。
SockJS 客户端开始发送 GET /info
,以从服务器获得基本信息。之后,它必须决定使用何种传输方式。如果可能的话,会使用 WebSocket。如果没有,在大多数浏览器中,至少有一个 HTTP 流选项。如果没有,则使用 HTTP(长)轮询。
所有传输请求都有以下 URL 结构:
https://host:port/myApp/myEndpoint/{server-id}/{session-id}/{transport}
其中:
{server-id}
在集群中路由请求时很有用,但在其他方面不使用。{session-id}
关联属于 SockJS 会话的 HTTP 请求。{transport}
表示传输类型(例如,websocket、xhr-streaming 和其他)。
WebSocket 传输只需要一个 HTTP 请求来完成 WebSocket 握手。此后的所有消息都在该套接字上进行交换。
HTTP 传输需要更多的请求。例如,Ajax/XHR 流依赖于一个用于服务器到客户端消息的长期请求和用于客户端到服务器消息的额外 HTTP POST 请求。长时间轮询也是类似的,只是它在每次服务器到客户端的发送之后都会结束当前的请求。
SockJS 增加了最小的消息框架。例如,服务器最初发送字母 o("open" frame)
,消息以 a["message1", "message2"]
(JSON 编码的数组)的形式发送,如果 25 秒内没有消息流动(默认),则发送字母 h("heartbeat" frame)
,并发送字母 c("close" frame)
以关闭会话。
要了解更多,请在浏览器中运行一个例子,并观察 HTTP 请求。SockJS 客户端允许固定传输列表,因此有可能一次看到每个传输。SockJS 客户端还提供了一个调试标志,它可以在浏览器控制台中启用有用的信息。在服务器端,你可以为 org.springframework.web.socket
启用 TRACE 日志。欲了解更多细节,请参阅 SockJS 协议的 叙述性测试。