Web Socket
Web端即时通讯技术
因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询、Comet技术、WebSocket技术、SSE(Server-sent Events)。
Web Socket(套接字)的目标是通过一个长时连接
实现在用户的浏览器和服务器之间打开双工、双向通讯会话。
Web Socket使用了自定义协议,所以 URL方案稍有变化:不能再使用 http://或 https://,而要使用 ws://和 wss://
。前者是不安全的连接,后者是安全连接。
WebSocket 与 HTTP 和 HTTPS 使用相同的 TCP 端口,可以绕过大多数防火墙的限制。
创建Web Scocket对象
创建一个新的 Web Socket,就要实例化一个 WebSocket 对象并传入提供连接的 URL:
let socket = new WebSocket("ws://www.example.com/server.php")
必须给 WebSocket 构造函数传入一个绝对 URL
。同源策略不适用于 Web Socket,因此可以打开到任意站点的连接。
浏览器会在初始化 WebSocket 对象之后立即创建连接。
与 XHR 类似,WebSocket 也有一个
readyState
属性表示当前状态。 WebSocket.OPENING(0):连接正在建立。
WebSocket.OPEN(1):连接已经建立。
WebSocket.CLOSING(2):连接正在关闭。
WebSocket.CLOSE(3):连接已经关闭。
WebSocket 对象没有 readystatechange 事件,而是有与上述不同状态对应的其他事件。
readyState 值从 0 开始。
任何时候都可以调用 close()方法
关闭 Web Socket 连接:socket.close()
;
调用 close()之后,readyState 立即变为 2(连接正在关闭),并会在关闭后变为 3(连接已经关闭)。
发送和接收数据
除了文本,WebSocket消息还可以处理二进制数据,这种数据作为Blob消息或ArrayBuffer消息。
打开 Web Socket 之后,要向服务器发送数据,使用 send()方法
并传入一个字符串、ArrayBuffer 或 Blob,如下所示:
let socket = new WebSocket("ws://www.example.com/server.php");
let stringData = "Hello world!";
let arrayBufferData = Uint8Array.from(['f', 'o', 'o']);
let blobData = new Blob(['f', 'o', 'o']);
socket.send(stringData);
socket.send(arrayBufferData.buffer);
socket.send(blobData);
接收到来自服务端的消息时,WebSocket 对象上会触发 message事件
。这个 message 事件与其他消息协议类似,可以通过 event.data 属性访问到有效载荷:
socket.onmessage = function(event) {
let data = event.data;
// 对数据执行某些操作
};
其他事件
open:在连接成功建立时触发。
error:在发生错误时触发。连接无法存续。
close:在连接关闭时触发。
let socket = new WebSocket("ws://www.example.com/server.php");
socket.onopen = function() {
alert("与服务端连接打开");
};
在这些事件中,只有 close 事件的 event 对象上有额外信息。这个对象上有 3 个额外属性: wasClean、code 和 reason。其中,wasClean 是一个布尔值,表示连接是否干净地关闭;code 是一 个来自服务器的数值状态码;reason 是一个字符串,包含服务器发来的消息。可以将这些信息显示给 用户或记录到日志:
socket.onclose = function(event) {
console.log(`as clean? ${event.wasClean} Code=${event.code} Reason=${
event.reason}`);
};
总结
优点:
- 实时性:WebSocket提供了实时的双向数据传输,能够实现高效的实时通信,而不需要通过轮询或长轮询等间接方式。
- 低延迟:由于WebSocket建立在TCP连接上,并且使用更轻量级的协议头部,因此可以减少数据传输的延迟,提供更快速的响应时间。
- 节省带宽:WebSocket使用较少的网络流量,因为它使用更紧凑和有效的数据帧格式,并且可以使用二进制数据传输,而不仅仅是文本数据。
- 更强大的功能:相比于HTTP请求-响应模型,WebSocket支持服务器主动推送数据到客户端,从而能够实现实时更新、即时聊天、多人协作和实时数据展示等功能。
- 兼容性:WebSocket协议被广泛支持,并且现代的Web浏览器都原生支持WebSocket,无需任何额外插件或库。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据
。在 WebSocket API 中,浏览器和服务器只需要完成一次握手
,两者之间就可以创建持久性的连接
,并进行双向数据传输。
WebSocket被广泛应用于实时数据传输、在线聊天、多人游戏、实时协作、股票行情、推送通知、实时监控等场景,为Web应用程序提供了更好的用户体验和功能扩展性。
扩展: WebSocket与SockJs、STOMP关系
由于一些浏览器不支持WebSocket协议,所以在项目中经常使用SockJs结合STOMP来实现WebSocket订阅消息!在此不详细介绍使用方法,简单了解下是什么吧~
SockJS
是一个JavaScript库,为了应对许多浏览器不支持WebSocket协议的问题
,设计了备选SockJs。SockJS 是 WebSocket 技术的一种模拟。SockJS会尽可能对应 WebSocket API,但如果WebSocket 技术不可用的话,会自动降为轮询的方式。
SockJS的url是
http、https协议
,而不是 ws,提供Websocket兼容性实现方法。
new WebSocket(url) url必须是以ws://或者wss://开始的一个完全限定URL。
SockJS会优先选择WebSocket进行连接,但是当服务器或客户端不支持WebSocket时,会自动在 XHR流、XDR流、iFrame事件源、iFrame HTML文件、XHR轮询、XDR轮询、iFrame XHR轮询、JSONP轮询 这几个方案中择优进行连接。
直接使用 WebSocket(SockJS) 就很类似于 使用 TCP 套接字来编写 web 应用,因为没有高层协议,就需要我们定义应用间所发送消息的语义,还需要确保连接的两端都能遵循这些语义。
STOMP
STOMP(-面向消息的简单文本协议)在WebSocket之上提供了一个基于帧的线路格式层,用来定义消息的语义
。
STOMP帧由命令、一个或多个头信息以及负载所组成。
前后端websocket都用stomp才有意义!
总结:WebSocket 是底层协议,SockJS 是WebSocket 的备选方案,也是底层协议,而 STOMP 是基于 WebSocket(SockJS)的上层协议。