初识WebSocket

HTTP 协议特色

  • 单向请求
  • 无状态
  • 半双工

通讯只能由客户端主动发起请求来获取服务端数据javascript

WebSocket是什么

WebSocket是一种能够建立和服务器间进行 双向会话 的高级技术,经过WebSocket能够向服务器发送消息并接受基于事件驱动的响应。这样就不用向服务器轮询获取数据。html

双向会话:客户端和服务端都可以经过WebSocket来进行数据相互传递,即服务端能够给客户端推送数据,客户端也能够经过WebSocket向服务端传递数据。java

为何要使用WebSocket?

在不使用WebSocket时,咱们须要创建长链接时。创建长链接的几种主要方法:web

  • 轮询
  • 长轮询
  • SSE(Server Send Event)

轮询

轮询是最先在客户端用来模拟长链接的一种方式。他经过客户端定时向服务端发送HTTP请求来模拟客户端向服务端发送数据,而服务端的数据则是在客户端发送HTTP请求后跟随返回
缺点: 服务端的数据须要在客户端的请求回来后才能带回。若是HTTP请求的间隔过短,则会致使大量的网络开销;若是间隔太长,这将致使数据传递的不及时api

长轮询

长轮询是在轮询的基础上改进的一种方式。在客户端发送HTTP请求且服务端收到请求时,服务端会先维持这个请求不返回。在特定的时间内(通常为30秒,由于一般HTTP判断超时时间为30秒),若是服务端没有数据,则回应这个请求;服务端有数据须要发送时,则当即经过HTTP请求的响应将数据传递给客户端。客户端收到响应后,当即发起下一次的HTTP请求。
优缺点:可以解决轮询中带来的服务端数据不能及时传递的问题,可是带来的网络花销大的问题仍然没法解决服务器

SSE(Server Send Event)

SSE一种新的协议,用于服务端向客户端推送数据,经过SSE实现数据的单向推送功能。
缺点: 单向推送,只能从服务端向客户端推送数据、websocket

WebSocket可以解决的问题

WebSocket可以有效的解决上述问题,还包括如下问题:网络

  1. 带宽问题:WebSocket相对HTTP协议头更小,按需传递数据
  2. 数据实时性问题:WebSocket相对轮询和长轮询来讲可以实时传递数据,延迟更少
  3. 状态问题:相对无状态的HTTP,WebSocket在创建链接后会维持特定的状态

WebSocket协议

WebSocket协议是由HTTP协议升级而来的,只要在HTTP协议的基础上增长两次握手(若是是须要经过SSL加密,则还须要进行SSL握手过程),便可创建WebSocket链接。如下Header相关字段socket

请求Header

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13性能

其中:

  • Host: server.example.com:表示将要链接的WebSocket地址。
  • Connection: Upgrade:表示HTTP链接须要升级
  • Upgrade: websocket:表示将HTTP链接升级为WebSocket链接
  • Sec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ==:客户端生成的WebSocket密钥
  • Sec-WebSocket-Protocol: chat, superchat:指定客户端那些WebSocket协议是能够接受的
  • Sec-WebSocket-Version: 13:指定WebSocket版本

响应Header

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

其中:

  • Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo:服务端根据客户端生成的链接密钥生成服务端密钥
  • Connection: Upgrade:确认升级HTTP链接
  • Upgrade: websocket:确认将HTTP链接升级为WebSocket链接
  • Sec-WebSocket-Protocol: chat:服务端选择的WebSocket协议

WebSocket API

WebSocket的API比较简单,按使用顺序包括:

  • 创建链接
  • 接收消息
  • 发送消息
  • 关闭链接

创建链接

WebSocket 经过实例化来建立链接,经过实例的open事件的回调来确认链接建立成功,如:

const websocket = new WebSocket('ws://server.example.com');
websocket.addEventListener('open', e => {
    // 创建链接成功...
});

ps:在WebSocket创建ws链接时,url能够是域名或者IP地址;可是当创建的链接是wss(加密WebSocket)时,url必须是域名,由于须要配置相应的证书,而证书是针对域名的。

接收消息

WebSocket 经过message事件来监听消息接收,如:

websocket .addEventListener('message', e => {
    // 消息接收成功
});

WebSocket能够传递StringArrayBufferBlob三种数据类型,所以在收到消息时多是其中的任意一种。其中,StringArrayBuffer使用的最多。

发送消息

WebSocket 的发送消息是经过实例的send方法来实现的。

websocket.send(data);

关闭链接

被动关闭

当服务端被动关闭WebSocket链接时,会经过WebSocket向客户端发送一个close数据包,会触发实例的WebSocket close事件如:

websocket.addEventListener('close', e => {
    // WebSocket链接关闭
});

注:当网络断开时,WebSocket链接并不会被动关闭,由于没有收到关闭的数据包

主动关闭

客户端能够经过WebSocket提供的close方法来主动关闭长链接

websocket.close();

注:主动关闭不会触发close事件

其余客户端API

websocket.readyState
readyState属性返回实例对象的当前状态,共有四种

  • CONNECTING 值为0 表示正在链接
  • OPEN 值为1 表示已经链接,能够通讯
  • CLOSING 值为2 表示链接正在关闭
  • CLOSED 值为3 表示链接已经关闭

websocket.bufferedAmount
实例对象的bufferedAmount属性,表示还有多少字节的二进制数据没有发送出去,能够经过该属性来判断数据发送是否结束。

var data = new ArrayBuffer(10000000);
    socket.send(data);

    if (socket.bufferedAmount === 0) {
      // 发送完毕
    } else {
      // 发送还没结束
    }

websocket.binaryType
binaryType属性,显式指定收到的二进制数据类型

// 收到的是 blob 数据
websocket.binaryType = "blob";
websocket.onmessage = function(e) {
  console.log(e.data.size);
};

// 收到的是 ArrayBuffer 数据
websocket.binaryType = "arraybuffer";
websocket.onmessage = function(e) {
  console.log(e.data.byteLength);
};

总结

经过WebSocket的长链接,客户端和服务端能够进行大量的数据传输而不会带来相关的性能问题,这给Web端带来了极大的功能加强。目前Web端可使用WebSocket来进行IM相关功能开发,或者实时协做等须要与服务端进行大量数据交互的功能,而且不须要像以前同样使用长轮询的Hack方式来实现。

参考连接

WebSocket 教程

相关文章
相关标签/搜索