记录 创建一个SockJs包装过得websocket

什么是SockJS

SockJS是一个JavaScript库,提供跨浏览器JavaScript的API,创建了一个低延迟、全双工的浏览器和web服务器之间通信通道。

SockJS是用来干什么的

首先我们要了解一下 --webSocket--
  • 前端和后端的交互模式最常见的就是前端发数据请求,从后端拿到数据后展示到页面中。如果前端不做操作,后端不能主动向前端推送数据,这恰恰就是http协议的缺陷。但在我们平常开发中,常遇到客户端需要实时获取服务端信息,做到客户端与服务端互通有无,通过http协议实现(轮询)存在一定延时性,且会造成资源的很大浪费,websocket却能完美实现。恰巧最近有项目需求,就做了一定研究,特此记录。
  • 而有因为一些浏览器中缺少对WebSocket的支持,因此,回退选项是必要的,而Spring框架提供了基于SockJS协议的透明的回退选项。SockJS的一大好处在于提供了浏览器兼容性。优先使用原生WebSocket,如果在不支持websocket的浏览器中,会自动降为轮询的方式。
    除此之外,spring也对socketJS提供了支持。
    如果代码中添加了withSockJS()如下,服务器也会自动降级为轮询。
registry.addEndpoint("/coordination").withSockJS();
  • SockJS的目标是让应用程序使用WebSocket API,但在运行时需要在必要时返回到非WebSocket替代,即无需更改应用程序代码。SockJS是为在浏览器中使用而设计的。它使用各种各样的技术支持广泛的浏览器版本。对于SockJS传输类型和浏览器的完整列表,可以看到SockJS客户端页面。
    传输分为3类:WebSocket、HTTP流和HTTP长轮询(按优秀选择的顺序分为3类)

sockjs-client

SockJS模仿WebSockets API,但它不是WebSocket,而是一个SockJS Javascript对象。首先,您需要加载SockJS JavaScript库。例如,你可以把它放在你的HTML head里:

 <script src="https://cdn.bootcss.com/sockjs-client/1.0.0/sockjs.min.js"></script>

(如果有错误提示可以更换版本号!!!)

sockjs-client建立连接

加载脚本后,你可以建立与SockJS服务器的连接(下面这个是我自己项目中的例子)

 // 创建一个有SockJs包装过的webSocket
    var socket = new SockJS(`/dorm/websocket`);
    //StompJS 简单流文本定向消息协议
    stompClient = Stomp.over(socket);
    // 发送频率
    stompClient.heartbeat.outgoing = 20000;
    // client will send heartbeats every 20000ms
    // 接收频率
    stompClient.heartbeat.incoming = 0;
    stompClient.connect({}, function (frame) {
      // setConnected(true);
      // 订阅和接受消息
      stompClient.subscribe("/topic/message/" + dormId, function (response) {
        var xx = JSON.parse(response.body);
        personList.push(xx);
      });
    });

接下来就解释一下具体该如何使用

sockjs-client构造函数的参数

var sockjs = new SockJS(url, _reserved, options);

url:后端提供的消息推送的接口
options是一个散列,它可以包含:

1.server: 类型String,默认值-随机4位数字,其会被添加到url上作为实际数据连接。
2.transports: 类型字符串或者字符串数组。此选项允许您提供可由SockJS使用的列表传输。默认情况下,所有可用的传输都将被使用,但有时需要禁用一些回退传输是有用的。
2.sessionId: 类型number或者function。客户端和服务器都使用会话标识符来区分连接。如果将这个选项指定为一个数字,那么SockJS将使用它的随机字符串生成器函数来生成一个N字符长的会话id(其中N对应于sessionId指定的数字)。当您将此选项指定为函数时,函数必须返回一个随机生成的字符串。每次SockJS需要生成一个会话id时,它将调用该函数并直接使用返回的字符串。如果没有指定此选项,默认情况是使用默认的随机字符串生成器生成8个字符的长会话id。

我们再来说说例子中的Stomp是干什么用的

STOMP:即简单(流)文本定向消息协议。用于连接到企业消息代理,它被设计用于处理常用消息传递模式的最小功能子集,STOMP可以用于任何可靠的双向流网络协议,如TCP和WebSocket,虽然STOMP是一个面向文本的协议,但消息payload可以是文本或二进制。就像HTTP在TCP套接字之上添加了请求-响应模型层一样,STOMP 在 WebSocket 之上提供了一个基于帧的线路格式(frame-based wire format)层,用来定义消息的语义。STOMP是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议,它提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互,用于client之间进行异步消息传输的简单文本协议。

Stomp.over

浏览器提供了不同的WebSocket的协议,一些老的浏览器不支持WebSocket的脚本或者使用别的名字。默认下,stomp.js会使用浏览器原生的WebSocket class去创建WebSocket。利用Stomp.over(ws)这个方法可以使用其他类型的WebSockets。这个方法得到一个满足WebSocket定义的对象。
例如,可以使用由SockJS实现的Websocket:

首先引入这个js
 <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<script>
    var ws = new SockJS(url);
    var client = Stomp.over(ws);
  ...
</script>

如果使用原生的Websockets就使用Stomp.client(url),如果需要使用其他类型的Websocket(例如由SockJS包装的Websocket)就使用Stomp.over(ws)。
除了初始化有差别,Stomp API在这两种方式下是相同的。

client.heartbeat.outgoing/incoming(心跳检测)

客户端client对象有一个字段 heartbeat ,通过改变incoming和outgoing数值,来配置心跳频率(默认频率值为:10000ms)

client.heartbeat.outgoing = 20000; // 客户端每20000ms发送一次心跳检测
client.heartbeat.incoming = 0; // client不接收serever端的心跳检测

client.connect

Stomp 客户端建立了,必须调用它的connect()方法去连接,从而Stomp服务端进行验证。这个方法需要两个参数,用户的登录和密码凭证。
这种情况下,客户端会使用Websocket打开连接,并发送一个CONNECT frame。
这个连接是异步进行的:你不能保证当这个方法返回时是有效连接的。为了知道连接的结果,你需要一个回调函数。
connect()方法可接受不同数量的参数来提供简单的API:

client.connect(login, passcode, connectCallback);
client.connect(login, passcode, connectCallback, errorCallback);
client.connect(login, passcode, connectCallback, errorCallback, host);

Subscribe(订阅)和receive(接收)消息

为了在浏览器中接收消息,STOMP客户端必须先订阅一个目的地destination。
你可以使用subscribe()去订阅。这个方法有2个必需的参数:目的地(destination),回调函数(callback);还有一个可选的参数headers。其中destination是String类型,对应目的地,回调函数是伴随着一个参数的function类型(如图中示例)!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容