赞
踩
SockJS是一个浏览器JavaScript库,提供了一个类似websocket的对象。SockJS为您提供了一个连贯的,跨浏览器的Javascript API,它在浏览器和web服务器之间创建了一个低延迟,全双工,跨域通信通道。
实际上,SockJS首先尝试使用本地WebSockets。如果失败了,它可以使用各种特定于浏览器的传输协议,并通过类似websocket的抽象来表示它们。
SockJS旨在适用于所有现代浏览器和不支持WebSocket协议的环境——例如,在限制性的公司代理之后。
SockJS-client确实需要一个对应的服务器:
原则:
订阅SockJS邮件列表进行讨论和支持。
进行中的工作:
SockJS 模仿 WebSockets API,但不是 WebSocket
,而是 SockJS
Javascript 对象。
首先,您需要加载 SockJS JavaScript 库。 例如,你可以把它放在你的 HTML 头部:
<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
After the script is loaded you can establish a connection with the SockJS server. Here’s a simple example:
var sock = new SockJS('https://mydomain.com/my_prefix');
sock.onopen = function() {
console.log('open');
sock.send('test');
};
sock.onmessage = function(e) {
console.log('message', e.data);
sock.close();
};
sock.onclose = function() {
console.log('close');
};
与WebSocket
API 类似,SockJS
构造函数采用一个或多个参数:
var sockjs = new SockJS(url, _reserved, options);
url
可以包含一个查询字符串,如果需要的话。
其中 options
是一个散列,它可以包含:
server (字符串)
要附加到实际数据连接的 url 的字符串。 默认为随机的 4 位数字。
transports (字符串 或者 字符串数组)
有时禁用一些后备传输很有用。 此选项允许您提供 SockJS 可能使用的传输列表。 默认情况下,将使用所有可用的传输。
sessionId (数字 或者 函数)
客户端和服务器都使用会话标识符来区分连接。如果您将此选项指定为数字,SockJS 将使用其随机字符串生成器函数生成 N 个字符长的会话 ID(其中 N 对应于 sessionId 指定的数字)。当您将此选项指定为一个函数时,该函数必须返回一个随机生成的字符串。每次 SockJS 需要生成会话 ID 时,它都会调用此函数并直接使用返回的字符串。如果不指定此选项,则默认使用默认的随机字符串生成器生成 8 个字符的长会话 ID。
timeout (数字)
指定用于传输连接的最小超时时间(以毫秒为单位)。默认情况下,这是根据测量的 RTT 和预期往返次数动态计算的。此设置将建立一个最小值,但如果计算出的超时值更高,则会使用该值。
虽然 SockJS
对象试图模拟 WebSocket
行为,但不可能支持它的所有功能。SockJS 的一个重要限制是您不允许一次打开一个以上的 SockJS 连接到一个域。此限制是由传出连接的浏览器内限制引起的 - 通常浏览器不允许打开两个以上的传出连接到单个域。一个 SockJS 会话需要这两个连接 - 一个用于下载数据,另一个用于发送消息。同时打开第二个 SockJS 会话很可能会阻塞,并可能导致两个会话超时。
一次打开多个 SockJS 连接通常是一种不好的做法。如果你绝对必须这样做,你可以使用多个子域,为每个SockJS连接使用不同的子域。
译者白石注: 现代的浏览器早已支持同一个域可以打开多个连接了.
Browser | Websockets | Streaming | Polling |
---|---|---|---|
IE 6, 7 | no | no | jsonp-polling |
IE 8, 9 (cookies=no) | no | xdr-streaming † | xdr-polling † |
IE 8, 9 (cookies=yes) | no | iframe-htmlfile | iframe-xhr-polling |
IE 10 | rfc6455 | xhr-streaming | xhr-polling |
Chrome 6-13 | hixie-76 | xhr-streaming | xhr-polling |
Chrome 14+ | hybi-10 / rfc6455 | xhr-streaming | xhr-polling |
Firefox <10 | no ‡ | xhr-streaming | xhr-polling |
Firefox 10+ | hybi-10 / rfc6455 | xhr-streaming | xhr-polling |
Safari 5.x | hixie-76 | xhr-streaming | xhr-polling |
Safari 6+ | rfc6455 | xhr-streaming | xhr-polling |
Opera 10.70+ | no ‡ | iframe-eventsource | iframe-xhr-polling |
Opera 12.10+ | rfc6455 | xhr-streaming | xhr-polling |
Konqueror | no | no | jsonp-polling |
有时您可能希望从“file://”地址提供您的 html - 用于开发或者如果您正在使用 PhoneGap 或类似技术。但是由于跨源策略,从“file://”提供的文件没有源,这意味着某些 SockJS 传输将无法工作。由于这个原因,SockJS 传输表与通常不同,主要区别是:
Browser | Websockets | Streaming | Polling |
---|---|---|---|
IE 8, 9 | no | iframe-htmlfile | iframe-xhr-polling |
Other | same as above | iframe-eventsource | iframe-xhr-polling |
Transport | References |
---|---|
websocket (rfc6455) | [rfc 6455]2 |
websocket (hixie-76) | [draft-hixie-thewebsocketprotocol-76]3 |
websocket (hybi-10) | [draft-ietf-hybi-thewebsocketprotocol-10]4 |
xhr-streaming | Transport using [Cross domain XHR]5 [streaming]6 capability (readyState=3). |
xdr-streaming | Transport using [XDomainRequest]1 [streaming]6 capability (readyState=3). |
eventsource | [EventSource/Server-sent events]7. |
iframe-eventsource | [EventSource/Server-sent events]7 used from an [iframe via postMessage]8. |
htmlfile | [HtmlFile]9. |
iframe-htmlfile | [HtmlFile]9 used from an [iframe via postMessage]8. |
xhr-polling | Long-polling using [cross domain XHR]5. |
xdr-polling | Long-polling using [XDomainRequest]1. |
iframe-xhr-polling | Long-polling using normal AJAX from an [iframe via postMessage]8. |
jsonp-polling | Slow and old fashioned [JSONP polling]10. This transport will show “busy indicator” (aka: “spinning wheel”) when sending data. |
虽然 SockJS 的主要目的是启用浏览器到服务器的连接,但也可以从外部应用程序连接到 SockJS。任何符合 0.3 协议的 SockJS 服务器都支持原始 WebSocket url。测试服务器的原始WebSocket url如下所示:
您可以将任何符合 WebSocket RFC 6455 标准的 WebSocket 客户端连接到此 url。这可以是命令行客户端、外部应用程序、第三方代码甚至是浏览器(尽管我不知道您为什么要这样做)。
您应该使用支持服务器使用的协议的 sockjs-client 版本。 例如:
<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
关于服务器端部署技巧,特别是关于负载平衡和会话粘连的技巧,请参阅SockJS-node readme。
SockJS-client需要node.js来运行测试服务器和简化JavaScript。如果你想使用SockJS-client源代码,签出git repo并遵循以下步骤:
cd sockjs-client
npm install
要生成JavaScript,运行:
gulp browserify
要生成最小化的JavaScript,运行:
gulp browserify:min
这两个命令都输出到 build
目录。
由以下机构提供的自动化测试:
编译 SockJS-client 后,您可能想检查您的更改是否通过了所有测试。
npm run test:browser_local
这将启动 karma 和测试支持服务器。
我们不打算解决各种浏览器怪癖:
jsonp-polling
传输在发送数据时会显示一个“纺车”(又名“忙指示器”)。onmessage
的全局函数可能不是一个好主意,因为它可以由内置的 postMessage
API 调用。https://openbase.com/js/sockjs/documentation
通常 WebSockets 不能很好地与代理和负载均衡器一起使用。 在 Nginx 或 Apache 后面部署 SockJS 服务器可能会很痛苦。
幸运的是,一个优秀的负载均衡器HAProxy的最新版本能够代理WebSocket连接。我们建议将HAProxy作为前端负载均衡器,并使用它将 SockJS 流量与普通 HTTP 数据分开。查看示例 SockJS HAProxy 配置。
haproxy.cfg
文件:
# Requires recent Haproxy to work with websockets (for example 1.4.16). defaults mode http # Set timeouts to your needs timeout client 5s timeout connect 5s timeout server 5s frontend all 0.0.0.0:8888 mode http timeout client 120s option forwardfor # Fake connection:close, required in this setup. option http-server-close option http-pretend-keepalive acl is_sockjs path_beg /echo /broadcast /close acl is_stats path_beg /stats use_backend sockjs if is_sockjs use_backend stats if is_stats default_backend static backend sockjs # Load-balance according to hash created from first two # directories in url path. For example requests going to /1/ # should be handled by single server (assuming resource prefix is # one-level deep, like "/echo"). balance uri depth 2 timeout server 120s server srv_sockjs1 127.0.0.1:9999 # server srv_sockjs2 127.0.0.1:9998 backend static balance roundrobin server srv_static 127.0.0.1:8000 backend stats stats uri /stats stats enable
该配置还展示了如何使用 HAproxy 平衡在多个 Node.js 服务器之间拆分流量。 您还可以使用 DNS 名称进行平衡。
再看看一个生产上的支持 Websocket 的 HAProxy 配置(haproxy.cfg
):
global maxconn 4096 # Total Max Connections. This is dependent on ulimit nbproc 2 log 127.0.0.1 local1 notice defaults mode http log global frontend all 0.0.0.0:80 timeout client 86400000 default_backend www_backend acl is_websocket hdr(Upgrade) -i WebSocket acl is_websocket hdr_beg(Host) -i ws acl host_bibliaolvaso hdr_sub(Host) -i bibliaolvaso.hu acl host_todomvc hdr_sub(Host) -i todomvc use_backend bibliaolvaso_backend if is_websocket host_bibliaolvaso use_backend todomvc_backend if is_websocket host_todomvc backend www_backend balance roundrobin option forwardfor # This sets X-Forwarded-For timeout server 86400000 timeout connect 4000 server nginx localhost:81 backend bibliaolvaso_backend balance roundrobin option forwardfor # This sets X-Forwarded-For timeout queue 5000 timeout server 86400000 timeout connect 5000 server bibliaolvaso localhost:7777 backend todomvc_backend balance roundrobin option forwardfor # This sets X-Forwarded-For timeout queue 5000 timeout server 86400000 timeout connect 5000 server todomvc localhost:3003
如果您计划部署多个SockJS服务器,则必须确保单个会话的所有HTTP请求都将命中同一个服务器。SockJS有两种机制可以实现这一点:
/resource/<server_number>/<session_id>/transport
。 这对于支持基于前缀的关联(HAProxy 支持)的负载均衡器很有用。JSESSIONID
cookie 由 SockJS 节点设置。 如果设置了该 cookie,许多负载平衡器会打开粘性会话。 此技术源自 Java 应用程序,其中通常需要粘性会话。 HAProxy 以及一些托管服务提供商(例如 CloudFoundry)确实支持这种方法。 为了在客户端启用此方法,请向 SockJS 构造函数提供 cookie:true
选项。SockJS 节点不会向应用程序公开 cookie。 这是故意这样做的,因为在 SockJS 中使用基于 cookie 的授权根本没有意义,并且会导致安全问题。
cookie是浏览器和http服务器之间的契约,由域名标识。如果浏览器为特定的域设置了cookie,它将把它作为所有http请求的一部分传递给主机。但是为了让各种传输工作,SockJS使用了一个中间人
基本上- cookie不适合SockJS模型。如果你想授权一个会话-在一个页面上提供一个唯一的令牌,首先通过SockJS连接发送它,并在服务器端验证它。本质上,这就是cookie的工作原理。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。