肉渣教程

H5 Websocket

上一节 结束

上一节已经说了很多Websocket的特点,它是一种建立在TCP协议上、与HTTP/HTTPS协议良好兼容网络协议;而且Websocket是一种双向通信协议,可以让浏览器和服务器之间相互发送、接收数据。

用Websocket神功震断轮询的奇经八脉

啥是“轮询”?这就要说起HTTP/HTTPS协议的单向性:通信请求只能由客户端浏览器发起

举一个简单的例子,为了防止六大派进攻光明顶,于是在光明顶上建立了一个瞭望塔,当瞭望台可以记录方圆百里内的六大派敌人的数量(假设一个变量n,瞭望得到敌人的数量都会保存在这个变量n中),在六大派没有发起进攻时,这个n则会等于0。

当时的光明左使负责防御,他要根据敌人数量n这个值来进行部署,所以他(客户端)只能是每隔几秒钟通过HTTP/HTTPS请求来向瞭望塔(服务器)发起请求来询问获得当前n变量的值。这就是所谓的轮询。

轮询并不明智,只是限制于当时的方式方法。首先,轮询对瞭望塔(服务器)的资源造成大幅消耗浪费;而且轮询纵使间隔时间很短,但终究是有时间间隔的,即时性无法到达炉火纯青的境界。

后来,明教有新教主了,遂教大家用了一套新的神功大法,就是传说中的Websocket;有了Websocket这种协议,光明左使(客户端)只要用Websocket的方式连上瞭望塔(服务器),只要瞭望塔(服务器)发现新的六大派的敌人,瞭望塔(服务器)就会主动把此时的n值(敌人总数量)发送给刚才已经连上瞭望塔的光明左使(客户端)。

如此,不仅仅是性能开销小、通信更加即时;而且每次通信的数据量也变得更加轻量。因此,Websocket在六大派围攻光明顶一战中,为明教立下了汗马功劳。

Websocket的特点

  • 建立在TCP协议上
  • 与HTTP/HTTPS协议具有良好的兼容性,握手阶段采用HTTP/HTTPS协议;
  • 连接上后每次数据交互的数据很轻量,性能开销小,有助于更加高效地通信;
  • 投过Websocket协议,服务器可以主动发数据给客户端,从而避免了轮询,在应用层面,大大增加了通信的高效即时性;
  • 既可以发送文本、也可以发送二进制数据;
  • 并不要求与HTML页面本站处于相同的域名之下,换言之,天生支持跨域请求
  • 协议标识符为ws(如果ssl加密则为wss),例如ws://xxx.com/xxx

浏览器兼容性

Websocket协议最早出现于2008年,于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。现在几乎所有的浏览器都支持Websocket协议;下表为各浏览器支持Websocket的最低版本:

API
Websocket 4.0 10.0 6.0 5.0 12.0

Websocket 示例

这里使用第三方网站提供的一个Websocket协议的接口( wss://echo.websocket.org )用来测试;第三方Websocket服务器端定的规则是客户端发送什么数据过去,服务器则返回同样的数据。示例比较简单,代码如下:

var ws = new WebSocket("wss://echo.websocket.org");

ws.onopen = function(event) { 
  alert("连接连上咯~"); 
  ws.send("为人民服务~");
};

ws.onmessage = function(event) {
  alert( "服务器发过来的数据是: " + event.data);
  ws.close();
};

ws.onclose = function(event) {
  alert("连接关闭了。");
};

运行一下

WebSocket对象

上例中通过WebSocket类构造了一个WebSocket实例对象,即ws变量。

var ws = new WebSocket("wss://echo.websocket.org");

当用上述方法创建WebSocket实例时,客户端就会与服务器进行握手连接。而WebSocket实例对象常用的一些属性如下所示:

属性 说明
readyState 返回当前连接状态,共有4种状态
CONNECTING,值为0,表示正在连接;
OPEN,值为1,表示连接握手成功,可以进行通信;
CLOSING,值为2,表示连接正在关闭;
CLOSED,值为3,表示连接已经关闭或连接失败。
bufferedAmount 返回当前还剩多少字节的即将发送的二进制数据
用于判断发送是否结束(只读)
url 返回该Websocket请求的URL绝对地址(只读)
例如返回“wss://echo.websocket.org”
binaryType 返回二进制数据所使用的格式,有2种格式
blob(二进制大对象)、arraybuffer(二进制数组)
onopen 事件监听器 - 连接成功
onmessage 事件监听器 - 收到服务器端发送信息
onclose 事件监听器 - 连接断开
onerror 事件监听器 - 发生错误


WebSocket实例对象的方法如下表所列:

方法 说明
close([code[, reason]]) 断开与服务器的连接
send(data) 向已连接的服务器端发送数据


更多关于Websocket的属性和方法参考这里


onopen回调函数

WebSocket实例对象的onopen属性可用于指定连接成功后的回调函数。

ws.onopen = function(event) { 
  alert("连接连上咯~"); 
  ws.send("为人民服务~");
};

也可通过addEventListener方法进行添加,该方法的好处是可添加不止一个回调函数:

ws.addEventListener('open', function (event) {
  alert("连接连上咯~"); 
  ws.send("为人民服务~");
});

onmessage回调函数

WebSocket实例对象的onmessage属性可用于指定收到服务器端发送信息后的回调函数。

ws.onmessage = function(event) {
  alert( "服务器发过来的数据是: " + event.data);
  ws.close();
};

也可通过addEventListener方法进行添加,该方法的好处是可添加不止一个回调函数:

ws.addEventListener('message', function (event) {
  alert( "服务器发过来的数据是: " + event.data);
  ws.close();
});

onclose回调函数

WebSocket实例对象的onclose属性可用于指定Websocket连接断开而触发的回调函数。

ws.onclose = function(event) {
  alert("连接关闭了。");
};

也可通过addEventListener方法进行添加,该方法的好处是可添加不止一个回调函数:

ws.addEventListener('close', function (event) {
  alert("连接关闭了。");
});

send方法

WebSocket实例对象的send方法可向已握手连接的服务器发送数据:

ws.send( "为人民服务~" );

关于Websocket的服务器端:大部分服务器程序都会有实现Websocket的模块或者外部插件;在此推荐两款可以写Websocket服务器端的框架:Websocketd(后端开发语言没有限制)Tornado(基于Python的Web服务器框架)


H5 Websocket

上一节 结束