JavaScript Web Socket 详解

Web Socket

​ Web Socket(套接字)的目标是通过一个长时连接实现与服务器全双工、双向的通信。在 JavaScript 中创建 Web Socket 时,一个 HTTP 请求会发送到服务器以初始化连接。服务器响应后,连接使用 HTTP 的 Upgrade 头部从 HTTP 协议切换到 Web Socket 协议。这意味着 Web Socket 不能通过标准 HTTP 服务器实现,而必须使用支持该协议的专有服务器。

​ 因为 Web Socket 使用了自定义协议,所以 URL方案(scheme)稍有变化:不能再使用 http://或 https://, 而要使用 ws://和 wss://。前者是不安全的连接,后者是安全连接。在指定 Web Socket URL 时,必须包含 URL 方案,因为将来有可能再支持其他方案。

​ 使用自定义协议而非 HTTP 协议的好处是,客户端与服务器之间可以发送非常少的数据,不会对 HTTP 造成任何负担。使用更小的数据包让 Web Socket 非常适合带宽和延迟问题比较明显的移动应用。 使用自定义协议的缺点是,定义协议的时间比定义 JavaScript API 要长。Web Socket 得到了所有主流浏览器支持。

Web Socket 是与服务器的全双工、双向通信渠道。与其他方案不同,Web Socket 不使用 HTTP,而使用了自定义协议,目的是更快地发送小数据块。这需要专用的服务器,但速度优势明显。

API

​ 要创建一个新的 Web Socket,就要实例化一个 WebSocket 对象并传入提供连接的 URL

let socket = new WebSocket("ws://www.example.com/server.php"); 

​ 注意,必须给 WebSocket 构造函数传入一个绝对 URL同源策略不适用于 Web Socket,因此可以打开到任意站点的连接。至于是否与来自特定源的页面通信,则完全取决于服务器。(在握手阶段就可以确定请求来自哪里。)

浏览器会在初始化 WebSocket 对象之后立即创建连接。与 XHR 类似,WebSocket 也有一个 readyState 属性表示当前状态。不过,这个值与 XHR 中相应的值不一样。

  • 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(连接已经关闭)。

发送和接收数据

​ 打开 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; 
    // 对数据执行某些操作
};

​ 与通过 send() 方法发送的数据类似,event.data 返回的数据也可能是 ArrayBuffer 或 Blob。 这由 WebSocket 对象的 binaryType 属性决定,该属性可能是"blob"或"arraybuffer"。

其他事件

​ WebSocket 对象在连接生命周期中有可能触发 3 个其他事件。

  • open:在连接成功建立时触发。
  • error:在发生错误时触发。连接无法存续。
  • close:在连接关闭时触发。

​ WebSocket 对象不支持 DOM Level 2 事件监听器,因此需要使用 DOM Level 0 风格的事件处理程序来监听这些事件:

let socket = new WebSocket("ws://www.example.com/server.php"); 
socket.onopen = function() { 
    alert("Connection established."); 
}; 
socket.onerror = function() { 
    alert("Connection error."); 
}; 
socket.onclose = function() { 
    alert("Connection closed."); 
}; 

​ 在这些事件中,只有 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}`); 
};

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值