我们可以通过wss.clients获得当前已连接的所有客户端,然后遍历,得到实例,调用send()方法发送数据;
var clients = wss.clients, len = clients.length, i = 0; for( ; i < len; i = i + 1 ){ clients[i].send( msg ); }说到这里,一个双向通信的实例基本完成,当然,上面都是伪代码,完整的demo请查看附件。
除了常见的聊天程序以外,大家完全可以发挥创意,构建一些“好玩”的应用;
接下来,分享另外一个应用,“你画我猜”这个应用,很多人都接触过,大致上是:某个人在屏幕上画一些图形,这些图片会实时展示在其它人的屏幕上,然后来猜画的是什么。
利用WebSocket和canvas,我们可以很轻松的构建类似的应用。当然,我们这里只是demo,并没有达到产品级的高度,这里只是为大家提供思路;
首先,我们再次明确一下,WebSocket赋予了我们在浏览器端和服务器进行双向通信的能力,这样,我们可以实时的将数据发送给服务器,然后再广播给所有的客户端。这和聊天程序的思路是一致的。
接下来,服务器端的代码不用做任何修改,在html页面中准备一个canvas,作为我们的画布。如何在canvas上用鼠标画图形呢?我们需要监听mousedown、mousemove和mouseup三个鼠标事件。说到这里,大家应该知道怎么做了。没错,就是在按下鼠标的时候,记录当前的坐标,移动鼠标的时候,把坐标发送给服务器,再由服务器把坐标数据广播给所有的客户端,这样就可以在所有的客户端上同步绘画了;最后,mouseup的时候,做一些清理工作就ok了。下面是一些伪代码:
var WhiteBoard = function( socket, canvasId ){ var lastPoint = null, mouseDown = false, canvas = getById(canvasId), ctx = canvas.getContext('2d'); var handleMouseDown = function(event) { mouseDown = true; lastPoint = resolveMousePosition.bind( canvas, event )(); }; var handleMouseUp = function(event) { mouseDown = false; lastPoint = null; }; var handleMouseMove = function(event) { if (!mouseDown) { return; } var currentPoint = resolveMousePosition.bind( canvas, event )(); socket.send(JSON.stringify({ event: 'draw', data: { points: [ lastPoint.x, lastPoint.y, currentPoint.x, currentPoint.y ] } })); lastPoint = currentPoint; }; var init = function(){ addEvent( canvas, 'mousedown', handleMouseDown ); addEvent( canvas, 'mouseup', handleMouseUp ); addEvent( canvas, 'mousemove', handleMouseMove ); var img = new Image(); addEvent( img, 'load', function(e){ canvas.width = img.width; canvas.height = img.height; ctx.drawImage( img, 0, 0 ); } ); img.src = '/img/diablo3.png'; }; var drawLine = function(data) { var points = data.points; ctx.strokeStyle = 'rgb(255, 15, 255)'; ctx.beginPath(); ctx.moveTo( points[0] + 0.5, points[1] + 0.5 ); ctx.lineTo( points[2] + 0.5, points[3] + 0.5 ); ctx.stroke(); }; function resolveMousePosition(event) { var x, y; if (event.offsetX) { x = event.offsetX; y = event.offsetY; } else { //(注意)实际开发中,这样获取鼠标相对canvas的坐标是不对的 x = event.layerX - this.offsetLeft; y = event.layerY - this.offsetTop; } return { x: x, y: y }; }; init(); return { draw : drawLine //ctx : ctx, //canvas : canvas } }( websocket, 'drawsomething' );对于canvas不熟悉的同学,请自己去搜索一下,有许多不错的教程。其它方面,和聊天应用的思路基本一样。
最后,我们需要明确一点,WebSocket本身的优点很明显,但是作为一个正在演变中的web规范,我们必须清楚的认识到WebSocket在构建应用时的一些风险;虽然本身有很多局限性,但是这项技术本身肯定是大势所趋,WebSocket在移动终端,在chrome web store都有用武之地,我们可以进行大胆的尝试,让我们在技术的革新中不被淘汰。
Resources:
W3 API的官方文档,有详细的接口设计文档和实现步骤
WebSocket协议
Known Issues and Best Practices for the Use of Long Polling and Streaming in Bidirectional HTTP
(v=vs.85).aspx
msdn中关于WebSocket的介绍
https://developer.mozilla.org/en/WebSockets
#feat=websockets
Compatibility tables for support of HTML5, CSS3, SVG and more in desktop and mobile browsers.