SockJS-client简介

news2025/1/10 23:50:02

概述

SockJS是一个浏览器JavaScript库,提供了一个类似websocket的对象。SockJS为您提供了一个连贯的,跨浏览器的Javascript API,它在浏览器和web服务器之间创建了一个低延迟,全双工,跨域通信通道。

实际上,SockJS首先尝试使用本地WebSockets。如果失败了,它可以使用各种特定于浏览器的传输协议,并通过类似websocket的抽象来表示它们。

SockJS旨在适用于所有现代浏览器和不支持WebSocket协议的环境——例如,在限制性的公司代理之后。

SockJS-client确实需要一个对应的服务器:

  • SockJS-node 是Node.js的SockJS服务器。

原则:

  • API应该尽可能地遵循 HTML5 Websockets API。
  • 所有传输必须支持开箱即用的跨域连接。可以并且建议将SockJS服务器托管在与主网站不同的服务器上。
  • 每个主流浏览器都至少支持一种流协议。
  • 流传输应该跨域工作,并且应该支持cookie(用于基于cookie的粘滞会话)。
  • 轮询传输用作旧浏览器和受限制代理后面的主机的回退。
  • 连接建立应快速、轻便。
  • 内部没有Flash(不需要打开端口843 -不需要通过代理工作,不需要托管’crossdomain.xml’,不需要等待3秒以检测问题)

订阅SockJS邮件列表进行讨论和支持。

SockJS 家族

  • SockJS-client JavaScript client library
  • SockJS-node Node.js server
  • SockJS-erlang Erlang server
  • SockJS-cyclone Python/Cyclone/Twisted server
  • SockJS-tornado Python/Tornado server
  • SockJS-twisted Python/Twisted server
  • SockJS-aiohttp Python/Aiohttp server
  • Spring Framework Java client & server
  • vert.x Java/vert.x server
  • Xitrum Scala server
  • Atmosphere Framework JavaEE Server, Play Framework, Netty, Vert.x
  • Actix SockJS Rust Server, Actix Framework

进行中的工作:

  • SockJS-ruby
  • SockJS-netty
  • SockJS-gevent (SockJS-gevent fork)
  • pyramid-SockJS
  • wildcloud-websockets
  • wai-SockJS
  • SockJS-perl
  • SockJS-go
  • syp.biz.SockJS.NET - .NET port of the SockJS client

开始

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');
 };

SockJS-client API

SockJS 类

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连接使用不同的子域。

译者白石注: 现代的浏览器早已支持同一个域可以打开多个连接了.
在这里插入图片描述

支持的传输,按浏览器(从 http:// 或 https:// 提供的 html)

BrowserWebsocketsStreamingPolling
IE 6, 7nonojsonp-polling
IE 8, 9 (cookies=no)noxdr-streaming †xdr-polling †
IE 8, 9 (cookies=yes)noiframe-htmlfileiframe-xhr-polling
IE 10rfc6455xhr-streamingxhr-polling
Chrome 6-13hixie-76xhr-streamingxhr-polling
Chrome 14+hybi-10 / rfc6455xhr-streamingxhr-polling
Firefox <10no ‡xhr-streamingxhr-polling
Firefox 10+hybi-10 / rfc6455xhr-streamingxhr-polling
Safari 5.xhixie-76xhr-streamingxhr-polling
Safari 6+rfc6455xhr-streamingxhr-polling
Opera 10.70+no ‡iframe-eventsourceiframe-xhr-polling
Opera 12.10+rfc6455xhr-streamingxhr-polling
Konquerornonojsonp-polling
  • : IE 8+ 支持[XDomainRequest][1](https://github.com/sockjs/sockjs-client#user-content-fn-9-a585ebdccb2f8f0e0f2f1a448ce422c1), 它本质上是一个修改后的 AJAX/XHR,可以跨域进行请求。 但不幸的是,它不发送任何 cookie,这使得它不适合在负载均衡器使用 JSESSIONID cookie 进行粘性会话时进行部署。
  • : Firefox 4.0和Opera 11.00,并附带禁用Websockets“hixie-76”。 它们仍然可以通过手动更改浏览器设置来启用。

支持的传输,由浏览器(从 file:// 提供的 html)

有时您可能希望从“file://”地址提供您的 html - 用于开发或者如果您正在使用 PhoneGap 或类似技术。但是由于跨源策略,从“file://”提供的文件没有源,这意味着某些 SockJS 传输将无法工作。由于这个原因,SockJS 传输表与通常不同,主要区别是:

BrowserWebsocketsStreamingPolling
IE 8, 9noiframe-htmlfileiframe-xhr-polling
Othersame as aboveiframe-eventsourceiframe-xhr-polling

支持的传输,按名称

TransportReferences
websocket (rfc6455)[rfc 6455]2
websocket (hixie-76)[draft-hixie-thewebsocketprotocol-76]3
websocket (hybi-10)[draft-ietf-hybi-thewebsocketprotocol-10]4
xhr-streamingTransport using [Cross domain XHR]5 [streaming]6 capability (readyState=3).
xdr-streamingTransport 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-pollingLong-polling using [cross domain XHR]5.
xdr-pollingLong-polling using [XDomainRequest]1.
iframe-xhr-pollingLong-polling using normal AJAX from an [iframe via postMessage]8.
jsonp-pollingSlow and old fashioned [JSONP polling]10. This transport will show “busy indicator” (aka: “spinning wheel”) when sending data.

在没有客户端的情况下连接到 SockJS

虽然 SockJS 的主要目的是启用浏览器到服务器的连接,但也可以从外部应用程序连接到 SockJS。任何符合 0.3 协议的 SockJS 服务器都支持原始 WebSocket url。测试服务器的原始WebSocket url如下所示:

  • ws://localhost:8081/echo/websocket

您可以将任何符合 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 和测试支持服务器。

浏览器怪癖

我们不打算解决各种浏览器怪癖:

  • 在 Firefox 20 之前,在 Firefox 中按 ESC 会关闭 SockJS 连接。有关解决方法和讨论,请参阅 #18。
  • jsonp-polling 传输在发送数据时会显示一个“纺车”(又名“忙指示器”)。
  • 由于浏览器的并发连接限制,您不能同时打开多个SockJS连接到一个域(此限制不包括本机WebSocket连接)。
  • 虽然SockJS正在尝试转义任何奇怪的Unicode字符(甚至是无效字符-像替身\xD800-\xDBFF 或 \xFFFE和\xFFFF),但建议只使用有效字符。使用无效字符有点慢,并且可能不适用于具有适当 Unicode 支持的 SockJS 服务器。
  • 拥有一个名为 onmessage 的全局函数可能不是一个好主意,因为它可以由内置的 postMessage API 调用。
  • 从 SockJS 的角度来看,SSL/HTTPS 没有什么特别之处。未加密和加密站点之间的连接应该可以正常工作。
  • 尽管 SockJS 尽最大努力支持基于前缀和基于 cookie 的粘性会话,但后者可能无法与默认情况下不接受第三方 cookie 的浏览器 (Safari) 跨域良好地工作。为了解决这个问题,请确保您从与主站点相同的父域连接到 SockJS。例如,如果您从“www.a.com”或“a.com”连接,“sockjs.a.com”能够设置 cookie。
  • 尝试从安全的“https://”连接到不安全的“http://”不是一个好主意。反过来应该没问题。
  • 众所周知,长轮询会导致 Heroku 出现问题,但 SockJS 的解决方法可用。
  • SockJS websocket传输在SSL上更稳定。如果你是一个严肃的SockJS用户,那么考虑使用SSL(更多信息)。

各种问题和设计注意事项

WebSocket兼容的负载均衡器

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有两种机制可以实现这一点:

  • URL 以服务器和会话 ID 编号为前缀,例如:/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使用了一个中间人

  • 一个来自目标SockJS域的iframe。这意味着服务器将从iframe接收请求,而不是从真实域接收请求。iframe的域和SockJS的域是一样的。问题是任何网站都可以嵌入iframe并与之通信-并请求建立SockJS连接。在这种情况下,使用cookie进行授权将导致从任何网站授予SockJS与您的网站通信的完全访问权。这是典型的CSRF攻击。

基本上- cookie不适合SockJS模型。如果你想授权一个会话-在一个页面上提供一个唯一的令牌,首先通过SockJS连接发送它,并在服务器端验证它。本质上,这就是cookie的工作原理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/194091.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机网络入门(网络协议篇)

计算机网络分类虽然网络类型的划分标准各种各样&#xff0c;但是从地理范围划分是一种大家都认可的通用网络划分标准。按这种标准可以把各种网络类型划分为局域网、城域网、广域网三种。局域网一般来说只能是一个较小区域内&#xff0c;城域网是不同地区的网络互联&#xff0c;…

什么是进取心?如何提高进取心?

1、什么是进取心&#xff1f;进取心是一种心理状态&#xff0c;说的是积极上进&#xff0c;不断对自己提高要求&#xff0c;促使自己持续发展的心态。不论是学习还是工作&#xff0c;进取心都是我们获取成就的必备。从人的一生来说&#xff0c;进取心是我们探索人生最宝贵的修养…

ADB 开启 USB调试后,无法自动弹出调试授权窗口的解决方法

之前介绍了 Android Device Unauthorized 的解决方案&#xff0c;这次将分享 开启 USB调试后&#xff0c;无法自动弹出调试授权窗口的解决方法。即使选择在 “仅充电” 的情况下去调试&#xff0c;结果都一样。 在我自己的工程机 (荣耀系列的) 连上电脑后&#xff0c;USB 连接方…

《深入浅出计算机组成原理》学习笔记 Day18

冒险和预测&#xff08;二&#xff09;1. NOP 操作和指令对齐2. 操作数前推参考1. NOP 操作和指令对齐 MIPS 体系结构下的 R、I、J 三类指令&#xff1a; 五级流水线“取指令&#xff08;IF&#xff09;— 指令译码&#xff08;ID&#xff09;— 指令执行&#xff08;EX&…

linux_进程间通信 IPC

文章目录1、管道1.1、匿名管道1.2、有名管道2、信号3、共享内存3.1、共享内存接口3.1.1、生成 key 值3.1.2、创建共享内存3.1.3、创建共享内存映射3.1.4、解除共享内存映射3.1.5、修改共享内存属性3.2、例&#xff1a;共享内存4、信号量4.1、信号量的接口4.1.1、创建信号量4.1.…

第二章 RISC-V 指令集架构

前言 提醒&#xff1a;全文10千字&#xff0c;预计阅读时长15分钟&#xff1b;读者&#xff1a;对 RISC-V 架构感兴趣的小伙伴&#xff1b;目的&#xff1a;读者利用15~30 分钟对本文沉浸式阅读理解&#xff0c;能够掌握 RISC-V 架构 80% 的要点&#xff1b;关键词 &#xff1a…

Mysql 高级学习笔记

Mysql 高级学习笔记 文章目录Mysql 高级学习笔记一、Mysql 基础1. 聚合函数2. having3. sql 的执行顺序4. 约束5. 试图二、Mysql 高级1. MySQL中的SQL的执行流程2. 存储引擎介绍2. 索引3. 性能分析工具的使用4. 索引优化与查询优化5、关联查询优化6、事务及日志6、MVCC一、Mysq…

【C++】从0到1入门C++编程学习笔记 - 提高编程篇:STL常用容器(deque容器)

文章目录一、deque容器基本概念二、deque构造函数三、deque赋值操作四、deque 大小操作五、deque 插入和删除六、deque 数据存取七、deque 排序一、deque容器基本概念 功能&#xff1a; 双端数组&#xff0c;可以对头端进行插入删除操作 deque与vector区别&#xff1a; vec…

【Python】在代码中执行终端命令并获取输出和运行状态

文章目录0 前言1 os库1.1 os.system1.2 os.popen2 subprocess库2.1 subprocess.run2.2 subprocess.Popen3 参考链接0 前言 在Python编程过程中&#xff0c;我们可能会遇到需要在终端命令行执行某个命令并获取其输出的操作&#xff0c;我们首先想到可能就是C语言中的system(&quo…

字节青训营——分布式学习笔记

1. 分布式事务 满足ACID&#xff08;原子性、一致性、隔离性、持久性&#xff09;的一组操作&#xff0c;可以被称为一个事务。 同样的&#xff0c;分布式事务也部分遵循 ACID 规范&#xff1a; 原子性&#xff1a;严格遵循一致性&#xff1a;事务完成后的一致性严格遵循&am…

超详细域名备案+阿里云服务器配置+小程序开发(简略)+前后端分离(简略)

文章目录前言一、试水环节&#xff08;配置阿里云服务器环境&#xff09;二、购买域名及备案1.购买域名2.域名备案3.域名解析4.白嫖SSL证书5.在网站上链接备案号三、设置微信小程序开发的权限四、安装微信小程序开发的工具五、前后端分离&#xff08;简略&#xff09;总结前言 …

RPA自动化办公06——Uibot中的UB编程语言基础

参考&#xff1a;UB语言参考_UiBot开发者指南 虽然Uibot用命令就行&#xff0c;但是编程习惯会让程序员们更喜欢看源代码&#xff0c;有时候写源代码会更加方便&#xff0c;所有要学习UB的语言基础。 它很简单&#xff0c;和Python很像&#xff0c;下面简单了解一个各种基础语…

美团:前景乐观但风险巨大

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 增长势头强劲&#xff0c;已经扭亏为盈 过去几年&#xff0c;美团&#xff08;03690&#xff09;的收入一直在以两位数的速度在增长。 这一增长势头&#xff0c;到了2022年还在延续&#xff08;美团的收入在2022年仍保持…

kob配置git环境与项目创建

配置git环境 1.安装Git Bash 如果是使用Linux和mac可以跳过第一步操作&#xff0c;如果使用windows需要安装Git Bash:Git Bash传送门安装过程中所有配置按照默认即可&#xff1b; 2.配置Git环境 2.0 创建秘钥&#xff1a;使用命令&#xff1a;“ssh-keygen”生成秘钥&#…

【Java基础】多线程学习

1.多进程和多线程 多进程&#xff1a; 是指操作系统能同时运行多个任务&#xff08;程序&#xff09;。 多线程&#xff1a; 是指在同一程序中有多个顺序流在执行。 实现&#xff1a; 在java中要想实现多线程&#xff0c;有两种手段&#xff0c;一种是继承Thread类&#xff…

1、环境安装

目录一、vscode插件二、设置代理GOPROXY三、gopls1 - vscode弹出插件支持安装2 - LSP3 - gopls四、vscode设置一、vscode插件 vscode插件商店 Go Team at Google&#xff1a;让vscode关联上go语言的开发环境 Outline Map&#xff1a;更好的代码大纲 二、设置代理GOPROXY…

操作系统进程同步

文章目录操作系统进程同步一.进程同步的基本概念1.两种形式的制约关系2.临界资源&#xff08;critical resource&#xff09;3.临界区&#xff08;critical section&#xff09;4.同步进制遵循的原则二.硬件同步机制1.关中断2.Test-and-Set 指令3.Swap指令实现进程互斥三.信号量…

mysql-视图的定义和简单使用

mysql-视图视图1. 视图的定义2.视图的创建规则和使用限制小结视图 1. 视图的定义 视图是虚拟的表。与包含数据的表不一样&#xff0c;视图只包含使用时动态检索数据的查询。 视图的一些常见应用&#xff1a; 重用SQL语句。 简化复杂的SQL操作。在编写查询后&#xff0c;可以…

c语言之链表

今天来介绍一下c语言如何手写一个单向链表&#xff0c;我们都知道链表是用来提高空间的利用效率的数据结构&#xff0c;其中包括了一个数据域和指针域&#xff0c;数据域用来存储数据&#xff0c;指针域用来指向下一个节点。数据结构如下 我们都知道数据结构最主要的是他的增删…

从底层入手搞定C++引用和内联函数

C引用和内联函数 文章目录C引用和内联函数一、引用1.1引用的概念1.1.1代码展示1.1.2图示1.2引用的特性1.3常引用1.4引用的使用场景1.5 传值、传引用效率比较1.6 引用和指针的区别二、内联函数2.1.内联函数的概念2.2内联函数的特性总结一、引用 首先我们来看一下引用的概念&…