[TEAP早期試讀]基於WebSocket的聯機作圖例子

秀野堂主發表於2012-02-15

圖靈社群按
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的一些經驗

相關文章