qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問(wèn) http://qaseven.github.io/

          日立扶梯項(xiàng)目功能測(cè)試

           對(duì)于試用期新人來(lái)說(shuō)沒(méi)正事做,并不等于沒(méi)事做。一些練練手的東西還是源源不斷的。這兩天在搗鼓日立扶梯項(xiàng)目的一些功能。其實(shí)這項(xiàng)目還未正式簽約的,但一些功能上的實(shí)踐還是必須的。這項(xiàng)目是日立公司應(yīng)用于新品發(fā)布會(huì),運(yùn)用Flash動(dòng)態(tài)畫面,實(shí)時(shí)展示他們扶梯的安全性。日立對(duì)扶梯運(yùn)行狀況進(jìn)行實(shí)時(shí)監(jiān)控,將一些扶梯的運(yùn)行數(shù)據(jù)從服務(wù)端傳輸?shù)娇头耍簿褪瞧桨咫娔X。這是基于C/S模式的,F(xiàn)lash在這方面的應(yīng)用我也是首次嘗試。

            Flash對(duì)實(shí)時(shí)數(shù)據(jù)傳輸提供了套接字連接,也即是Socket連接。AS3.0提供兩種不同類型的套接字連接,XML套接字連接的XMLSocket類和二進(jìn)制套接字連接的Socket類。對(duì)于我來(lái)說(shuō)如果服務(wù)器能發(fā)送XML數(shù)據(jù)過(guò)來(lái)當(dāng)然是最好的,但可惜服務(wù)器是傳輸十六進(jìn)制的數(shù)據(jù)的。相對(duì)XMLSocket來(lái)說(shuō),Socket數(shù)據(jù)處理更為底層,可操控范圍更大,但難度也較大。

            對(duì)于實(shí)時(shí)傳輸數(shù)據(jù)有幾大有解決的問(wèn)題,如何持續(xù)正確連接,如何處理粘包,如何緩存數(shù)據(jù)等。正確連接,可以采用類似三次握手原則,服務(wù)端向服務(wù)器發(fā)起連接請(qǐng)求,服務(wù)器接收后返回一個(gè)驗(yàn)證碼,客服端接收到后確認(rèn)可以進(jìn)行連接,然后后向服務(wù)器發(fā)回一個(gè)指定的數(shù)據(jù),服務(wù)器確認(rèn)了數(shù)據(jù)的正確性再發(fā)送指令確認(rèn)客服端可以連接了。

            Flash的Socket連接是基于TCP的,所以不存在掉包的情況,最要是如何解決粘包或斷包。從網(wǎng)上看到一些解決法案是服務(wù)器發(fā)送的數(shù)據(jù)在包頭上加上數(shù)據(jù)長(zhǎng)度信息,當(dāng)客服端接收到數(shù)據(jù)包,先讀取信息頭,讀取指示后面的數(shù)據(jù)有多大。如果已經(jīng)讀了信息頭,則看能不能收到滿足條件的字節(jié)數(shù),若數(shù)據(jù)流里的數(shù)據(jù)滿足條件,開(kāi)始讀數(shù)據(jù),如果數(shù)據(jù)流里還未滿足讀取數(shù)據(jù)條件,則繼續(xù)讀取數(shù)據(jù)。至于如何緩存數(shù)據(jù),最簡(jiǎn)單的就是將數(shù)據(jù)保存到數(shù)組中,不過(guò)如何在適當(dāng)?shù)臅r(shí)候讀取數(shù)組中的數(shù)據(jù)還未想到較好的辦法。

          package
           {
               import flash.display.Sprite;
               import flash.net.Socket;
               import flash.events.IOErrorEvent;
               import flash.events.SecurityErrorEvent;
               import flash.events.ProgressEvent;
               import flash.events.Event;
               import flash.errors.IOError;
               import flash.events.MouseEvent;
               import flash.errors.EOFError;
               import flash.system.Security;
               import flash.utils.ByteArray;
               
               /**
                *
                * @author whk
                */
               public class SocketExample extends Sprite
               {
                   private var targetServer:String = "192.168.0.68"; //連接ip地址
                   private var port:uint = 9991; //連接端口        
                   private var socket:Socket;
                   private var str:String;
                   private var response:String;
                   private var msgLenMax:int; //收到的消息最大長(zhǎng)度
                   private var msgLen:int; //消息長(zhǎng)度
                   private var headLen:int; //消息頭長(zhǎng)度
                   private var isReadHead:Boolean; //是否已經(jīng)讀了消息頭
                   private var bytes:ByteArray; //所讀數(shù)據(jù)的緩沖數(shù)據(jù),讀出的數(shù)據(jù)放在這里
                   
                   public function SocketExample()
                   {
                       isReadHead = true;
                       headLen = 2; //2個(gè)字節(jié)
                       msgLenMax = 4028;
                       bytes = new ByteArray();
                       //Security.loadPolicyFile("socket://"+targetServer+":"+port);
                       socket = new Socket();
                       btnSend.enabled = false;
                       btnConnect.addEventListener(MouseEvent.CLICK, btnHandler);
                   }
                   
                   /**
                    * 處理按鈕事件
                    */
                   private function btnHandler(event:MouseEvent):void
                   {
                       switch (event.target.name)
                       {
                           case "btnConnect": 
                               btnLabel();
                               break;
                           case "btnSend": 
                               sendRequest();
                               break;
                       }
                   }
                   
                   private function btnLabel():void
                   {
                       if (btnConnect.label == "連接" || btnConnect.label == "重新連接")
                       {
                           //注冊(cè)socket事件
                           configureListeners();
                           //進(jìn)行socket連接
                           connectToSocketServer();
                       }
                       if (btnConnect.label == "關(guān)閉連接")
                       {
                           if (socket.connected)
                           {
                               socket.close();
                               btnConnect.label = "連接";
                               pringMessage("客服端已關(guān)閉連接");
                           }
                       }
                   }
                   
                   /**
                    * 連接socket服務(wù)器
                    */
                   private function connectToSocketServer():void
                   {
                       try
                       {
                           socket.connect(targetServer, port);
                       }
                       catch (error:SecurityError)
                       {
                           pringMessage("SecurityError: " + error);
                       }
                   
                   }
                   
                   private function configureListeners():void
                   {
                       socket.addEventListener(Event.CONNECT, connectHandler);
                       socket.addEventListener(Event.CLOSE, closeHandler);
                       socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
                       socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
                       socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
                   }
                   
                   /**
                    * 連接成功
                    */
                   private function connectHandler(event:Event):void
                   {
                       btnSend.enabled = true;
                       btnConnect.label = "關(guān)閉連接";
                       pringMessage("連接成功" + "\n" + "connectHandler: " + event + "\n");
                       btnSend.addEventListener(MouseEvent.CLICK, btnHandler);
                       trace("connectHandler: " + event);
                       trace(txtRead.text);
                   }
                   
                   /**
                    * 向服務(wù)器發(fā)送數(shù)據(jù)
                    */
                   private function sendRequest():void
                   {
                       trace("sendRequest");
                       response = "";
                       //發(fā)送內(nèi)容
                       writeln("GET /");
                   }
                   
                   private function writeln(str:String):void
                   {
                       str += txtSend.text + "\n";
                       if (socket.connected)
                       {
                           try
                           {
                               //將UTF-8字符串寫入套接字
                               socket.writeInt(int(str));
                               txtRead.text += "發(fā)送數(shù)據(jù)的數(shù)據(jù):" + str;
                               socket.flush();
                           }
                           catch (error:IOError)
                           {
                               pringMessage("socket.flush error\n" + error);
                           }
                       }
                       else
                       {
                           //進(jìn)行socket連接
                           connectToSocketServer();
                       }
                   }
                   
                   /**
                    * 接收數(shù)據(jù),并讀取
                    */
                   private function socketDataHandler(event:ProgressEvent):void
                   {
                       trace("socketDataHandler: " + event);
                       readResponse();
                   }
                   
                   private function readResponse():void
                   {
                       try
                       {
                           //parseNetData();
                           var str:String = socket.readUTFBytes(socket.bytesAvailable);
                           response += str;
                           trace(response);
                           //遍歷數(shù)據(jù)包
                           while (socket.bytesAvailable)
                           {
                               var data:int = socket.readByte();
                               trace(data);
                           }
                           txtRead.text += "接收的數(shù)據(jù):" + str + "\n";
                       }
                       catch (error:IOError)
                       {
                           pringMessage("當(dāng)socket已關(guān)閉而去讀取時(shí)引發(fā)I/O 異常\n" + "socket.read error\n" + error);
                       }
                       catch (error:EOFError)
                       {
                           pringMessage("沒(méi)有數(shù)據(jù)可讀而讀取時(shí)引發(fā)EOF異常\n" + "socket.read error\n" + error);
                       }
                   
                   }
                   
                   /**
                    * 解析網(wǎng)絡(luò)數(shù)據(jù)流
                    * 根據(jù)信息頭長(zhǎng)度讀取數(shù)據(jù)
                    */
                   private function parseNetData():void
                   {
                       //如果需要讀信息頭
                       if (isReadHead)
                       {
                           if (socket.bytesAvailable >= headLen)
                           {
                               //讀出指示后面的數(shù)據(jù)有多大
                               msgLen = socket.readShort();
                               isReadHead = false;
                           }
                       }
                       //如果已經(jīng)讀了信息頭,則看能不能收到滿足條件的字節(jié)數(shù)
                       if (!isReadHead && msgLen <= msgLenMax)
                       {
                           //如果為0,表示收到異常消息
                           if (msgLen == 0)
                           {
                               //一般消息長(zhǎng)度為0的話,表示與服務(wù)器出了錯(cuò),或者即將被斷開(kāi)等,通知客戶端,進(jìn)行特別處理
                               return;
                           }
                           //數(shù)據(jù)流里的數(shù)據(jù)滿足條件,開(kāi)始讀數(shù)據(jù)
                           if (socket.bytesAvailable >= msgLen)
                           {
                               //指針回歸
                               bytes.position = 0;
                               //取出指定長(zhǎng)度的網(wǎng)絡(luò)字節(jié)
                               socket.readBytes(bytes, 0, msgLen);
                               isReadHead = true;
                           }
                       }
                       //如果數(shù)據(jù)流里還滿足讀取數(shù)據(jù)條件,繼續(xù)讀取數(shù)據(jù)
                       if (socket.bytesAvailable >= headLen)
                       {
                           parseNetData();
                       }
                   }
                   
                   /**
                    * socket服務(wù)器關(guān)閉連接
                    */
                   private function closeHandler(event:Event):void
                   {
                       btnConnect.label = "重新連接";
                       pringMessage("socke服務(wù)器已關(guān)閉\n" + "closeHandler: " + event);
                       trace("closeHandler: " + event);
                   }
                   
                   private function ioErrorHandler(event:IOErrorEvent):void
                   {
                       trace("ioErrorHandler: " + event);
                       pringMessage("輸入/輸出錯(cuò)誤并導(dǎo)致發(fā)送或加載操作失敗\n" + "ioErrorHandler: " + event);
                   }
                   
                   private function securityErrorHandler(event:SecurityErrorEvent):void
                   {
                       trace("securityErrorHandler: " + event);
                       pringMessage("嘗試連接到調(diào)用方安全沙箱外部的服務(wù)器或端口號(hào)低于 1024 的端口\n" + "securityErrorHandler: " + event);
                   }
                   
                   /**
                    * 將消息打印到屏幕
                    * @param m:打印的消息
                    */
                   private function pringMessage(m:String = null):void
                   {
                       txtError.visible = true;
                       if (m == null)
                       {
                           txtError.text = "";
                           txtError.visible = false;
                           return;
                       }
                       if (txtError.text == null)
                       {
                           txtError.text = "";
                           txtError.visible = false;
                       }
                       txtError.text = m;
                   }
               
               }
           }



          Socket三次握手例子:

          package 
           {
               import flash.display.Sprite;
               import flash.events.ProgressEvent;
               import flash.net.Socket;
               import flash.utils.ByteArray;
               /**
                *
                * 三次握手連接socket
                * 來(lái)源socket編程
                */
               public class SocketHandshake extends Sprite
               {
                   public const DETERMINE_VERSION:int = 0;
                   public const RECEIVE_CHALLENGE:int = 1;
                   public const NORMAL:int = 2;
                   private var stateMap:Object;
                   private var currentState:int;
                   private var socket:Socket;
                   public function SocketHandshake( )
                   {
                       stateMap = new Object( );
                       stateMap[DETERMINE_VERSION] = readVersion;
                       stateMap[RECEIVE_CHALLENGE] = readChallenge;
                       stateMap[NORMAL] = readNormalProtocol;
                       currentState = DETERMINE_VERSION;
                       socket = new Socket( );
                       socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );
                       socket.connect( "localhost", 9000 );
                       trace(currentState);
                   }
                   private function onSocketData( event:ProgressEvent ):void
                   {
                       trace(currentState);
                       var processFunc:Function = stateMap[currentState];
                       processFunc( );
                   }
                   private function readVersion( ):void
                   {
           
                       try
                       {
                           var version:int = socket.readInt();
                           trace(version);
                       }
                       catch (error:Error)
                       {
                           trace("error:"+error);
                       }
                       currentState = RECEIVE_CHALLENGE;
                       socket.writeInt( version );
                       socket.flush( );
                   }
                   private function readChallenge( ):void
                   {
                       var bytes:ByteArray = new ByteArray( );
                       socket.readBytes( bytes, 0, 8 );
                       currentState = NORMAL;
                       socket.writeBytes( bytes );
                       socket.flush( );
                   }
                   private function readNormalProtocol( ):void
                   {
                   }
               }
           }

          posted on 2012-09-10 10:01 順其自然EVO 閱讀(210) 評(píng)論(0)  編輯  收藏


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2012年9月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          30123456

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 宜君县| 大洼县| 丰镇市| 达日县| 宝鸡市| 涟水县| 横山县| 牙克石市| 深水埗区| 安泽县| 肥乡县| 武川县| 海伦市| 开鲁县| 苏州市| 平山县| 元朗区| 岗巴县| 江西省| 馆陶县| 三台县| 长泰县| 新营市| 紫云| 河池市| 漠河县| 栾城县| 望城县| 黔东| 临朐县| 江城| 东乌珠穆沁旗| 平武县| 霍林郭勒市| 潮州市| 潞西市| 峨山| 永宁县| 开鲁县| 武清区| 丹东市|