WebSocket 介绍(二)-WebSocket API
这一章介绍如何用WebSocket API来控制协议和创建应用,运用http://websocket.org 提供的现有WebSocket服务器,我们可以收发消息、创建一些简单的WebSocket应用。一步一步的学习使用WebSocket API,最后我们会讨论浏览器的支持度和连通性。这一章的重点是WebSocket 协议在Web客户端的应用,在稍后的章节会介绍WebSocket协议以及其使用环境。
综述:
入门:
// Create new WebSocket connection var ws = new WebSocket("ws://www.websocket.org"); //测试了下链接不上。
// Connecting to the server with one protocol called myProtocol var ws = new WebSocket("ws://echo.websocket.org", "myProtocol"); //myProtocol 是假设的一个定义好的且符合标准的协议。
你可以传递一个协议的数组。
var echoSocket = new WebSocket("ws://echo.websocket.org", ["com.kaazing.echo","example.imaginary.protocol"]) //服务端会选择其中一个使用 echoSocket.onopen = function(e) { // Check the protocol chosen by the server console.log(echoSocket.protocol); }
输出:com.kaazing.echo
WebSocket事件:
open:
// Event handler for the WebSocket connection opening ws.onopen = function(e) { console.log("Connection open..."); };
open事件触发的时候,意味着协议握手结束,WebSocket已经准备好收发数据。如果你的应用收到open事件,就可以确定服务端已经处理了建立连接的请求,且同意和你的应用通信。
Message:
// 接受文本消息的事件处理实例: ws.onmessage = function(e) { if(typeof e.data === "string"){ console.log("String message received", e, e.data); } else { console.log("Other message received", e, e.data); } };
除了文本消息,WebSocket消息机制还能处理二进制数据,有Blob和ArrayBuffer两种类型,在读取到数据之前需要决定好数据的类型。
// 设置二进制数据类型为blob(默认类型) ws.binaryType = "blob"; // Event handler for receiving Blob messages ws.onmessage = function(e) { if(e.data instanceof Blob){ console.log("Blob message received", e.data); var blob = new Blob(e.data); } };
//ArrayBuffer ws.binaryType = "arraybuffer"; ws.onmessage = function(e) { if(e.data instanceof ArrayBuffer){ console.log("ArrayBuffer Message Received", + e.data); // e.data即ArrayBuffer类型 var a = new Uint8Array(e.data); } };
Error
//异常处理 ws.onerror = function(e) { console.log("WebSocket Error: " , e); //Custom function for handling errors handleErrors(e); };
Close
当然你可以调用close方法断开与服务端的链接来触发onclose事件,
ws.onclose = function(e) { console.log("Connection closed", e); };
连接失败和成功的关闭握手都会触发关闭事件,WebSocket的对象的readyState属性就代表连接的状态(2代表正在关闭,3代表已经关闭)。关闭事件有三个属性可以用来做异常处理和重获: wasClean,code和reason。wasClean是一个bool值,代表连接是否干净的关闭。 如果是响应服务端的close事件,这个值为true,如果是别的原因,比如因为是底层TCP连接关闭,wasClean为false。code和reason代表关闭连接时服务端发送的状态,这两个属性和给入close方法的code和reason参数是对应的,稍后会描述细节。
WebSocket 方法:
WebSocket 对象有两个方法:send()和close()
send():
一旦在服务端和客户端建立了全双工的双向连接,可以使用send方法去发送消息,
//发送一个文本消息 ws.send("Hello WebSocket!");
当连接是open的时候send()方法传送数据,当连接关闭或获取不到的时候回抛出异常。一个通常的错误是人们喜欢在连接open之前发送消息。如下所示:
// 这将不会工作 var ws = new WebSocket("ws://echo.websocket.org") ws.send("Initial data");
正确的姿势如下,应该等待open事件触发后再发送消息。
var ws = new WebSocket("ws://echo.websocket.org") ws.onopen = function(e) { ws.send("Initial data"); }
如果想通过响应别的事件去发送消息,可以检查readyState属性的值为open的时候来实现。
function myEventHandler(data) { if (ws.readyState === WebSocket.OPEN) { //open的时候即可发送 ws.send(data); } else { // Do something else in this case. //Possibly ignore the data or enqueue it. } }
发送二进制数据:
// Send a Blob var blob = new Blob("blob contents"); ws.send(blob); // Send an ArrayBuffer var a = new Uint8Array([8,6,7,5,3,0,9]); ws.send(a.buffer);
Blob对象和JavaScript File API一起使用的时候相当有用,可以发送或接受文件,大部分的多媒体文件,图像,视频和音频文件。这一章末尾会结合File API提供读取文件内容来发送WebSocket消息的实例代码。
close()
使用close方法来关闭连接,如果连接以及关闭,这方法将什么也不做。调用close方法只后,将不能发送数据。
ws.close();
close方法可以传入两个可选的参数,code(numerical)和reason(string),以告诉服务端为什么终止连接。第三章讲到关闭握手的时候再详细讨论这两个参数。
// 成功结束会话 ws.close(1000, "Closing normally"); //1000是状态码,代表正常结束。
WebSocket 属性
WebSocket对象有三个属性,readyState,bufferedAmount和Protocol。
readyState:
WebSocket对象通过只读属性readyState来传达连接状态,它会更加连接状态自动改变。下表展示了readyState属性的四个不同的值。
属性
|
值
|
状态
|
WebSocket.CONNECTING
|
0 |
连接正在进行,但还没有建立
|
WebSocket.OPEN
|
1
|
连接已经建立,可以发送消息。 |
WebSocket.CLOSING
|
2
|
连接正在进行关闭握手 |
WebSocket.CLOSED
|
3
|
连接已经关闭或不能打开 |
了解当前连接的状态有助于我们调试。
bufferedAmount:
// 10k var THRESHOLD = 10240; //建立连接 var ws = new WebSocket("ws://echo.websocket.org"); // Listen for the opening event ws.onopen = function () { setInterval( function() { //缓存未满的时候发送 if (ws.bufferedAmount < THRESHOLD) { ws.send(getApplicationState()); } }, 1000); }; //使用bufferedAmount属性发送数据可以避免网络饱和。
protocol:
在构造函数中,protocol参数让服务端知道客户端使用的WebSocket协议。而WebSocket对象的这个属性就是指的最终服务端确定下来的协议名称,当服务端没有选择客户端提供的协议或者在连接握手结束之前,这个属性都是空的。
完整实例
<h2>Websocket Echo Client</h2> <div id="output"></div>
// 初始化连接和事件 function setup() { output = document.getElementById("output"); ws = new WebSocket("ws://echo.websocket.org/echo"); // 监听open ws.onopen = function (e) { log("Connected"); sendMessage("Hello WebSocket!"); } // 监听close ws.onclose = function (e) { log("Disconnected: " + e.reason); } //监听errors ws.onerror = function (e) { log("Error "); } // 监听 messages ws.onmessage = function (e) { log("Message received: " + e.data); //收到消息后关闭 ws.close(); } } // 发送消息 function sendMessage(msg) { ws.send(msg); log("Message sent"); } // logging function log(s) { var p = document.createElement("p"); p.style.wordWrap = "break-word"; p.textContent = s; output.appendChild(p); // Also log information on the javascript console console.log(s); } // Start setup();
判断浏览器是否支持:
if (window.WebSocket){ console.log("This browser supports WebSocket!"); } else { console.log("This browser does not support WebSocket."); }