以前的项目中使用了
websocket
、socketJS
,趁此机会将一些知识点及资料进行整理总结。正所谓温故而知新~
本文源地址: http://lsxj615.com/2016/08/14...javascript
按照惯例,在使用以前,先了解一下概念。php
websocket
是在html5
中提供了一种浏览器和服务器间进行全双工通信的网络技术。html
浏览器向服务端发送一个请求,经过报文头部Upgrade
来代表须要从HTTP
切换至Websocket
协议。html5
GET ws://echo.websocket.org/?encoding=text HTTP/1.1 Origin: http://websocket.org Cookie: __utma=99as Connection: Upgrade Host: echo.websocket.org Sec-WebSocket-Key: uRovscZjNol/umbTt5uKmw== Upgrade: websocket Sec-WebSocket-Version: 13
若是服务端理解websocket协议,它也是经过报文Upgrade
从HTTP转换为Websocket协议。java
HTTP/1.1 101 WebSocket Protocol Handshake Date: Fri, 10 Feb 2012 17:38:18 GMT Connection: Upgrade Server: Kaazing Gateway Upgrade: WebSocket Access-Control-Allow-Origin: http://websocket.org Access-Control-Allow-Credentials: true Sec-WebSocket-Accept: rLHCkw/SKsO9GAH/ZSFhBATDKrU= Access-Control-Allow-Headers: content-type
这个时候就创建起了websocket链接,基于TCP/IP。使用端口与HTTP(80)和HTTPS(443)同样。git
知道了什么是websocket,那么为何要使用websocket呢?除了websocket以外,浏览器进行即时通讯的方式还有如下几种:github
按期查询
每隔一个时间段就向服务器发送一个请求,请求服务器的最新数据再进行更新。但这样作的后果就是浪费大量流量,对服务端形成了巨大压力。web
Comet
基于http长链接的“服务器推”技术。客户端与服务器端保持一个长链接,只有客户端须要的数据更新时,服务器才主动将数据推送给客户端。有两种形式:spring
基于Ajax
的长轮询(long-polling)方式
浏览器发出XMLHttpRequest请求,服务器端接收到请求后,会阻塞请求直到有数据或者超时才返回,浏览器在处理请求返回信息(超时或有效数据)后再次发出请求,从新创建链接。在此期间服务器端可能已经有新的数据到达,服务器会选择把数据保存,直到从新创建链接,浏览器会把全部数据一次性取回。浏览器
基于Iframe
及htmlfile
的流(http streaming)方式
一般的作法是在页面中嵌入一个隐藏的iframe,而后让这个iframe的src属性指向咱们请求的一个服务端地址,而且为了数据更新,咱们将页面上数据更新操做封装为一个js函数,将函数名当作参数传递到这个地址当中。服务端收到请求后解析地址取出参数(客户端js函数调用名),每当有数据更新的时候,返回对客户端函数的调用,而且将要跟新的数据以js函数的参数填入到返回内容当中,例如返回“<script type="text/javascript">update("data")</script>”这样一个字符串,意味着以data为参数调用客户端update函数进行客户端view更新。
当应用程序有高吞吐量的需求,Comet的长轮询就不适合了。
SSE
SSE(服务端推送事件)是一种容许服务端向客户端推送新数据的HTML5技术。与websocket相比,WebSocket相较SSE最大的优点在于它是双向交流的,这意味向服务端发送数据就像从服务端接收数据同样简单。用SSE时,通常经过一个独立的Ajax请求从客户端向服务端传送数据。相对于WebSocket,这样使用Ajax会增长开销,但也就多一点点而已。
相比于间断的轮询或长轮询来模拟全双工链接的解决方式,Websocket极大的减小了没必要要的网络流量和延迟。除此以外,Websocket-based的应用减轻了服务器的负担,让现有的机器能支持更多的并发链接。以下图所示:
【如下例子来源于http://www.websocket.org/abou...】
只须要建立一个新的Websocket实例,提供一个URL,这个URL表示的是你但愿链接的那个end-point。以下所示。
须要注意的是: ws://
和wss://
的前缀表示了Websokcet和安全协议的Websocket链接。
var myWebsocket = new Websocket("ws://www.websocket.org");
在链接到一个端点发送消息以前,你能够将一系列的事件监听器来处理链接的生命周期的每一个阶段。以下所示:
myWebSocket.onopen = function(evt) { alert("Connection open ..."); }; myWebSocket.onmessage = function(evt) { alert( "Received Message: " + evt.data); }; myWebSocket.onclose = function(evt) { alert("Connection closed."); };
向服务端发送信息,只须要简单的send
并提供你但愿传递的内容。发送信息后,close
终止链接。以下所示:
myWebSocket.send("Hello WebSockets!"); myWebSocket.close();
咱们都知道,webscoket是HTML5的新玩意,那么兼容性方面,以下图所示:
能够看出IE8以及Android 4.3是不支持的。这个时候,咱们就能够来看看socketJS
的优点了。
SockJS is a browser JavaScript library that provides a WebSocket-like object. SockJS gives you a coherent, cross-browser, Javascript API which creates a low latency, full duplex, cross-domain communication channel between the browser and the web server.
socketJS
的一大好处在于提供了浏览器兼容性。优先使用原生websocket
,若是在不支持websocket
的浏览器中,会自动降为轮询的方式。
除此以外,spring
也对socketJS
提供了支持。若是代码中添加了withSockJS()
以下,服务器也会自动降级为轮询。
registry.addEndpoint("/coordination").withSockJS();
<script src="//cdn.jsdelivr.net/sockjs/1.0.0/sockjs.min.js"></script> var sock = new SockJS('/coordination'); sock.onopen = function() { console.log('open'); }; sock.onmessage = function(e) { console.log('message', e.data); }; sock.onclose = function() { console.log('close'); }; sock.send('test'); sock.close();
更多内容,可查看github地址:https://github.com/sockjs/soc...
经过以上部分咱们能够知道websocket
的优点,兼容性的问题socketJS
也帮咱们解决了。不过这个时候,我还要安利一个好东西,也就是Stomp
。
STOMP is a simple text-orientated messaging protocol. It defines an interoperable wire format so that any of the available STOMP clients can communicate with any STOMP message broker to provide easy and widespread messaging interoperability among languages and platforms (the STOMP web site has a list of STOMP client and server implementations.
具体内容,可查看官网:http://jmesnil.net/stomp-webs...。或者等我下一篇文章详谈吧~
参考资料: