WebSocket兼容到低版本瀏覽器

就目前而言,WebSocket是最好的Web通訊解決方案了。可是IE從10纔開始兼容它,對於目前大量IE8存在的市場,原生的WebSocket顯然不太實用,咱們須要低版本兼容的解決方案。因而我模擬WebSocket在瀏覽器上的行爲,用AS3寫了個兼容的版本。 
內容有點多,這篇只把演示給搞定,至於AS的源碼就丟到下一篇了。下面是效果圖: 

演示下載地址: WebSocket兼容到低版本瀏覽器(演示實例) 
頁面代碼比較簡單,用法和正常的WebSocket基本同樣,只是引用了WebSocket.js這個文件來兼容低版本瀏覽器。固然還有個WebSocket.swf須要放在與頁面相同的目錄下。 
<script src="WebSocket.js"></script>
<script>
onload=function(){
  var ws=new WebSocket("ws://127.0.0.1:8000");
  ws.onopen=function(){
    //握手成功
    send.removeAttribute("disabled");
    send.value="發送";
  };
  ws.onmessage=function(e){
    //收到消息,放到頁面上
    var dl,dt,dd,o=eval("("+e.data+")");
    dl=document.createElement("dl");
    dt=document.createElement("dt");
    dd=document.createElement("dd");
    dt.innerHTML=o.client;
    dd.appendChild(document.createTextNode(o.content));
    dl.appendChild(dt);
    dl.appendChild(dd);
    wall.appendChild(dl);
    wall.scrollTop=1E8; //滾動條移到底部
  };
  send.onclick=function(){
    //發送消息
    if(!message.value)return alert("請輸入內容");
    ws.send(message.value);
    message.value="";
  };
};
</script>
<style>
dl {margin:3px 10px;font:14px/20px Consolas,微軟雅黑;}
dt {color:blue;}
#wall {
  border:1px solid #CCC;width:200px;height:200px;
  overflow-y:auto;margin-bottom:10px;
}
</style>
<div id="wall"></div>
<input id="message" />
<input type="button" value="鏈接中···" id="send" disabled />
 服務器程序使用NodeJS代碼,隨手寫的聊天室功能,僅僅爲了實現功能而已,做爲演示代碼不要吐槽考慮的不夠周全。裏面的 decodeDataFrame 和 encodeDataFrame 在以前的文章中有出現過,這裏就不貼出來了。因爲須要兼容AS版,因此服務器程序須要比普通的WebSocket多一個AS的域安全驗證的步驟。這是關鍵所在,若是使用現成的WebSocket庫之類的東西可能得稍微修改源碼才能兼容AS版。 
var crypto=require('crypto');
var fs=require('fs');
var WS='258EAFA5-E914-47DA-95CA-C5AB0DC85B11';

var pool=[]; //鏈接池

require('net').createServer(function(o){
  var key;
  o.on('data',function(e){
    if(!key){
      var data=e.toString();
      //Flash握手
      if(data=='<policy-file-request/>\0')
        return fs.readFile('policy.txt',function(err,data){
          o.write(data+'\0');
        });
      //WebSocket握手
      if(key=data.match(/Sec-WebSocket-Key: (.+)|$/)[1])
        key=crypto.createHash('sha1').update(key+WS).digest('base64'),
        o.write([
          'HTTP/1.1 101 Switching Protocols',
          'Upgrade: websocket',
          'Connection: Upgrade',
          'Sec-WebSocket-Accept: '+key
        ].join('\r\n')+'\r\n\r\n');
    }else{
      //解析數據
      var frame=decodeDataFrame(e);
      //文本幀
      if(frame.Opcode==1){
        //轉義數據
        var content=frame.PayloadData.replace(/\W/g,function(e){
          e=e.charCodeAt(0).toString(16);
          if(e.length==3)e='0'+e;
          return '\\'+(e.length>2?'u':'x')+e;
        }),client=o.remoteAddress+":"+o.remotePort,buffer;
        //包裝成JSON格式,並作成一個數據幀
        buffer=encodeDataFrame({
          FIN:1,Opcode:1,
          PayloadData:'{"client":"'+client+'","content":"'+content+'"}'
        });
        //對全部鏈接廣播數據
        for(i=0;i<pool.length;i++)pool[i].write(buffer);
      };
    };
  });
  //斷開時從鏈接池中移除
  o.on("close",function(){
    for(i=0;i<pool.length;i++)if(pool[i]==o)pool.splice(i,1);
  });
  //放入鏈接池中
  pool.push(o);
}).listen(8000);
 Flash握手就是AS的域安全驗證,這個在以前的文章「 使用AS直接與服務器TCP通訊 」中有詳細的說過,其實就是加載一個策略文件給它。把這個過程嵌入到WebSocket的握手以前就行。 
WebSocket.js的代碼就不貼出來講明瞭。它負責構造一個相似原生WebSocket的接口的功能,裏面會對不兼容WebSocket的瀏覽器加載WebSocket.swf來使之兼容。 
這個程序也是最近剛寫的,存在漏洞在所不免,若是實用的話之後將慢慢完善它。html

相關文章
相關標籤/搜索