[size=0.76em]WebSockets
[size=0.76em]WebSockets 简介
[size=0.76em]在 Web 应用中,HTTP 协议决定了客户端和服务端连接是短连接,即客户端 Request,服务端 Response,连接断开。要想实现客户端和服务端实时通信,只能通过客户端轮询来实现。服务端推送数据也并不是字面上意思上的直接推,其实还是客户端自己取。WebSockets 是 HTML5 规范新引入的功能,用于解决浏览器与后台服务器双向通讯的问题,使用 WebSockets 技术,后台可以随时向前端推送消息,以保证前后台状态统一。
[size=0.76em]在 WebSockets 中使用 send 和 onmessage
[size=0.76em]由于文本主要介绍 postMessage(send) 和 onmessage 客户端 API 的应用,而 WebSockets 涉及到服务器端代码的实现,所以本文将选取最简单的服务器端框架来编写服务器代码。WebSockets 服务器端有 jetty 提供的基于 Java 的实现,有 WebSocket-Node 基于 node.js 的实现,在 .Net 4.5 中也直接提供了 WebSockets 的支持。本文将使用 WebSocket-Node 提供的示例代码,稍作修改作为 WebSockets 的服务器端。关于 node.js 的介绍以及使用请参考 node.js 官方网站
[size=0.76em]首先,需要在客户端通过 JavaScript 代码 new 一个 WebSocket 实例出来,参数是实现 WebSocket 服务器端 URL 地址。然后在这个实例上监听 onmessage 事件接收服务器端发送过来的数据。当然,客户端也可以调用 send 方法,发送数据到服务器端。
清单 6. 创建 WebSocket 对象,并监听 onmessage 事件
connect : function() { var location ="ws://localhost:8000/"; // 创建 WebSockets 并传入 WebSockets server 地址 this._ws =new WebSocket(location); this._ws.onmessage=this._onmessage; //WebSockets 还提供了 onopen 以及 onclose 事件 this._ws.onopen =this._onopen; this._ws.onclose =this._onclose; }
[size=0.76em]在 _onmessage 方法中,接收数据,并显示在页面上
清单 7. _onmessage 方法
_onmessage : function(event) { //event 参数中有 data 属性,就是服务器发送过来的数据 if (event.data) { var messageBox = document.getElementById('messageBox'); var spanText = document.createElement('span'); spanText.className ='text'; // 把服务器发送过来的数据显示在窗口中 spanText.innerHTML = event.data; var lineBreak = document.createElement('br'); messageBox.appendChild(spanText); messageBox.appendChild(lineBreak); messageBox.scrollTop = messageBox.scrollHeight - messageBox.clientHeight; } },
[size=0.76em]在 _onopen 方法中,调用 _send 方法发送一条消息到服务器端,告之连接已经建立。在 _onclose 方法中,把 WebSocket 的实例设置成 null,释放资源。
清单 8. _onopen,_onclose 以及 send 方法
_onopen : function() { server._send("Client:Open WebSockets,"+new Date()); }, //message 参数就是客户端向服务器端发送的数据 _send : function(message) { if (this._ws) this._ws.send(message); }, // 此方法提供外部代码调用 send : function(text) { if (text !=null&& text.length >0) server._send(text); }, _onclose : function(m) { this._ws =null; }
[size=0.76em]把这些方法封装在一个 server 对象中,方便提供外部调用。用户只需要先调用 server 的 connect 方法建立连接,然后调用 send 方法发送数据。
清单 9. 封装客户端实现
var server = { // 对外主要提供 connect 和 send 方法 connect : function() {...}, _onopen : function() {...}, _send : function(message) {...}, send : function(text) {...}, _onmessage : function(event) {...}, _onclose : function(m) {...} };
[size=0.76em]在服务器端,通过 JavaScript 语言简单修改 WebSocket-Node 中提供的 echo-server.js 示例即可。这里只展示关键代码部分,其它代码请参见 WebSocket-Node 示例。
清单 10. WebSockets 服务器端简单实现
// 监听客户端的连接请求 wsServer.on('connect', function(connection) { function sendCallback(err) { if (err) console.error("send() error: " + err); } // 监听客户端发送数据的请求 connection.on('message', function(message) { if (message.type === 'utf8') {// 区别客户端发过来的数据是文本还是二进制类型 connection.sendUTF( "Server:Get message:
"+message.utf8Data, sendCallback ); } else if (message.type === 'binary') { connection.sendBytes(message.binaryData, sendCallback); } }); connection.on('close', function(reasonCode, description) { }); });
图 4. 点击 Connect 按钮
图 5. 输入内容,单击 Send Message 按钮