图灵社区按
TEAP是什么?TEAP是Turingbook Early Access Program的简称,即早期试读,它公布的是图灵在途新书未经编辑的内容。一本书的写作周期约为3-6个月,如果在写作的时间里,作者就能够与读者进行沟通和交流,读者可以提前阅读将来才能出版的内容,作者也能收获宝贵的反馈意见。

本次TEAP公布的书是《论道HTML5》,欢迎在此与作者秀野堂主交流。本篇内容选自书中第6章。

WebSocket的实时性到底有多强?传输效率到底有多高?带着这些问题,我们进行了一个具有实用价值的试验。这个实验的主要工作就是联机作图。假定一个人在一台电脑上通过鼠标画图,画图客户端利用WebSocket将画图的动作发送到服务器上,服务器再将相关的数据广播到其它客户端中。这样,一个人画图,所有的人都可以看见,而其它人也可以画图,与其它人交流。这个例子在未来的教育平台、会议平台上都会有实用价值。

简要图表分析

通过分析,本例最重要的技术需求就是基于WebSocket的网络通信必须是高效和实时和持久化的,否则联机作图的体验就会非常差。而具体的实现就是实时的将鼠标在屏幕上的坐标传到服务器端,服务器端再广播到所在连接入服务器的客户端中。

enter image description here 基于WebSocket的联机工作原理图

WebSocket联机作图客户端

基于WebSocket的联机作图客户端,主要任务有两个:一是实时的将本机鼠标坐标发向服务器端;二是实时接收服务器端传来的广播,在本机画布上实时显示其它人的鼠标轨迹。我们在这里提供了完整的代码,而且此类应用极具市场价值,希望各行业内的读者多多联系自己的行业,设计出精彩的应用来。

代码如下:

<!doctype html>
<style>
body{padding:0px;margin:0px;}
canvas{float:left;}
</style>
<SCRIPT LANGUAGE="JavaScript">
var s = new WebSocket("ws://127.0.0.1:8000/");//连接sockets服务器
s.onopen = function(event){//当连接成功时
    console.log("连接成功了!");
}
s.onmessage = function(event){//当从服务器接收到信息时
    var x=event.data.split(",")[0].split(":")[1];//分解来自服务器端传来的数据
    var y=event.data.split(",")[1].split(":")[1]; //分解来自服务器端传来的数据
    pixl({"x":x,"y":y});//根据分解过来的数据进行绘图
console.log({"x":x,"y":y});
}
s.onclose = function(event){//当连接关闭时
    console.log("连接关闭了!");
}
function SelfXY(){//坐标捕捉函数
var yScrolltop;
var xScrollleft;
if (self.pageYOffset || self.pageXOffset){
            yScrolltop = self.pageYOffset;
            xScrollleft = self.pageXOffset;
    }else if (document.documentElement && document.documentElement.scrollTop || document.documentElement.scrollLeft ){
        yScrolltop = document.documentElement.scrollTop;
        xScrollleft = document.documentElement.scrollLeft;
    }else if (document.body) {
        yScrolltop = document.body.scrollTop;
        xScrollleft = document.body.scrollLeft;
    }
    arrayPageScroll = {x:xScrollleft+event.clientX,y:yScrolltop + event.clientY}
//更新显示当前坐标的数值
    document.getElementById("postion").innerHTML="your postion=x:"+arrayPageScroll.x+",y"+arrayPageScroll.y;
    //向服务器端发送当前鼠标的坐标位置
s.send("x:"+arrayPageScroll.x+",y:"+arrayPageScroll.y); 
}
//绘图函数
function pixl(data){
        var elem = document.getElementById('myCanvas');
        if (elem && elem.getContext) {
            var context = elem.getContext('2d');
            if (context){
                context.fillRect(data.x,data.y,3,3 );//在坐标data.x,data.y画一个3*3大小的矩形点
                }
            }
    }
//-->
</SCRIPT>
<body>
<canvas id="myCanvas" width="500" height="500" style="border:1px #000 solid;" onmousemove="SelfXY();">
    Fallback content, in case the browser does not support Canvas.
<br>
你的浏览器不支持canvas画图
</canvas>
<div id="postion"></div>
</body>
</html>

下图是演示两个不同的窗口同时在联机绘画时,产生的图形,当用户在A窗口按下鼠标画图时,B窗口也会同时显示与A窗口一模一样的内容,注意两个关键要点:一是同时显示,二是一模一样。

enter image description here

通过对Console控制台的监控,我们可以看见不断地有JSON化的xy坐标数据传入,而客户端就是接收这些服务器端传入的数据,并通过绘图函数,将其图形化显示出来而已。具体见下图。

enter image description here

WebSocket联机作图服务端

本联机作图例子的服务器端代码的主要任务就是一个:接收所有客户端传来的坐标数据,再广播转发给所有的客户端。使每个客户端都可以显示所有人的信息。

服务器端的代码如下:

var ws = require('websocket');
var server = ws.createServer();//创建WebSocket Server

server.addListener("connection", function(conn){ //当有客户端接入时
    conn.addListener("message", function(message){ //当收到客户端发送的信息时
        server.broadcast(message); //向所有客户端发送信息
        console.log("position:"+message);
        });
    conn.on('error',function(err){ //捕错处理
        console.log(conn.id+"have some error.");
        });
    });
server.addListener("close", function(conn){ //当有客户端断开连接时
    server.broadcast("Disconnected: "+conn.id); //向所有客户端发送信息
    });    
server.listen(8000); //启动服务监听8000端口
console.log('Hello handsome boy,Server is Runing:8000');

WebSocket联机作图控制台

在服务器端的Node.JS命令行模式下,输入Node draw_server.js即可运行。运行结果如图所示。

enter image description here

运行过程中产生的数据截图如下。

enter image description here

相关阅读:[TEAP]关于Canvas的一些经验