HTML5 WebSocket

参考
阮一峰 WebSocket 教程
WebSocket 是什么原理
WebSocket 浅析

《WebSocket详解(一):初步认识WebSocket技术》
《WebSocket详解(二):技术原理、代码演示和应用案例》
《WebSocket详解(三):深入WebSocket通信协议细节》
《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》
《WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)》
《WebSocket详解(六):刨根问底WebSocket与Socket的关系》

一、示例
var ws = new WebSocket('wss://example.com/socket'); 
// 创建安全WebSocket 连接(wss)
ws.onerror = function (error) { ... } 
// 错误处理
ws.onclose = function () { ... } 
// 关闭时调用
ws.onopen = function () { 
// 连接建立时调用
  ws.send("Connection established. Hello server!"); 
// 向服务端发送消息
}

ws.onmessage = function(msg) { 
// 接收服务端发送的消息
  if(msg.data instanceof Blob) { 
// 处理二进制信息
    processBlob(msg.data);
  } else {
    processText(msg.data); 
// 处理文本信息
  }
}

默认JavaScript里的WebSocket传输是采用字符串模式的,采用UTF-8编码。除了动态判断收到的数据类型,也可以使用binaryType属性,显式指定收到的二进制数据类型(blob对象或Arraybuffer对象,默认是blob)。

Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'

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

// 收到的是 ArrayBuffer 数据
ws.binaryType = "arraybuffer";
ws.onmessage = function(e) {
  console.log(e.data.byteLength);
};
二、兼容性和socket.io
HTML5 WebSocket_第1张图片
WebSocket浏览器支持情况

除了老而不化的Opera Mini外,所有的浏览器都支持WebSocket。

鉴于现在不同的平台及浏览器版本对WebSocket支持的不同,有开发者做了一个叫做socket.io 的为实时应用提供跨平台实时通信的库,我们可以使用它完成向WebSocket的切换。socket.io 旨在使实时应用在每个浏览器和移动设备上成为可能,模糊不同的传输机制之间的差异。socket.io 的名字源于它使用了浏览器支持并采用的 HTML5 WebSocket 标准,因为并不是所有的浏览器都支持 WebSocket ,所以该库支持一系列降级功能:

  • Websocket
  • Adobe:registered: Flash:registered: Socket
  • AJAX long polling
  • AJAX multipart streaming
  • Forever Iframe
  • JSONP Polling

在大部分情境下,你都能通过这些功能选择与浏览器保持类似长连接的功能。具体细节请看Socket.io。

三、WebSocket 有没有可能取代 AJAX ?

WebSocket的诞生本质上就是为了解决HTTP协议本身的单向性问题:请求必须由客户端向服务端发起,然后服务端进行响应。这个Request-Response的关系是无法改变的。对于一般的网页浏览和访问当然没问题,一旦我们需要服务端主动向客户端发送消息时就麻烦了,因为此前的TCP连接已经释放,根本找不到客户端在哪。

为了能及时从服务器获取数据,程序员们煞费苦心研究出来的各种解决方案其实都是在HTTP框架下做的妥协,没法子,浏览器这东西只支持HTTP,我们有什么办法。所以大家要么定时去轮询,要么就靠长连接——客户端发起请求,服务端把这个连接攥在手里不回复,等有消息了再回,如果超时了客户端就再请求一次——其实大家也懂,这只是个减少了请求次数、实时性更好的轮询,本质没变。

WebSocket就是从技术根本上解决这个问题的:看名字就知道,它借用了Web的端口和消息头来创建连接,后续的数据传输又和基于TCP的Socket几乎完全一样,但封装了好多原本在Socket开发时需要我们手动去做的功能。比如原生支持wss安全访问(跟https共用端口和证书)、创建连接时的校验、从数据帧中自动拆分消息包等等。

换句话说,原本我们在浏览器里只能使用HTTP协议,现在有了Socket,还是个更好用的Socket。

了解了WebSocket的背景和特性之后,就可以回答它能不能取代AJAX这个问题了:

对于服务器与客户端的双向通信,WebSocket简直是不二之选。如果不是还有少数旧版浏览器尚在服役的话,所有的轮询、长连接等方式早就该废弃掉。那些整合多种双向推送消息方式的库(如http://Socket.IO**、SignalR)当初最大的卖点就是兼容所有浏览器版本,自动识别旧版浏览器并采取不同的连接方式,现在也渐渐失去了优势——所有新版浏览器都兼容WebSocket,直接用原生的就行了。说句题外话,这点很像jQuery,在原生js难用时迅速崛起,当其他库和原生js都吸收了它的很多优势时,慢慢就不那么重要了。

但是,很大一部分AJAX的使用场景仍然是传统的请求-响应形式,比如获取json数据、post表单之类。这些功能虽然靠WebSocket也能实现,但就像在原本传输数据流的TCP之上定义了基于请求的HTTP协议一样,我们也要在WebSocket之上重新定义一种新的协议,最少也要加个request id用来区分每次响应数据对应的请求吧。……但是,何苦一层叠一层地造个新轮子呢?直接使用AJAX不是更简单、更成熟吗?

另外还有一种情况,也就是传输大文件、图片、媒体流的时候,最好还是老老实实用HTTP来传。如果一定要用WebSocket的话,至少也专门为这些数据专门开辟个新通道,而别去占用那条用于推送消息、对实时性要求很强的连接。否则会把串行的WebSocket彻底堵死的。

所以说,WebSocket在用于双向传输、推送消息方面能够做到灵活、简便、高效,但在普通的Request-Response过程中并没有太大用武之地,比起普通的HTTP请求来反倒麻烦了许多,甚至更为低效。每项技术都有自身的优缺点,在适合它的地方能发挥出最大长处,而看到它的几个优点就不分场合地全方位推广的话,可能会适得其反。

四、使用实例可以参考flv.js中的websocket-loader.js

你可能感兴趣的:(HTML5 WebSocket)