日立扶梯项目功能测试

对于试用期新人来说没正事做,并不等于没事做。一些练练手的东西还是源源不断的。这两天在捣鼓日立扶梯项目的一些功能。其实这项目还未正式签约的,但一些功能上的实践还是必须的。这项目是日立公司应用于新品发布会,运用Flash动态画面,实时展示他们扶梯的安全性。日立对扶梯运行状况进行实时监控,将一些扶梯的运行数据从服务端传输到客服端,也就是平板电脑。这是基于C/S模式的,Flash在这方面的应用我也是首次尝试。

  Flash对实时数据传输提供了套接字连接,也即是Socket连接。AS3.0提供两种不同类型的套接字连接,XML套接字连接的XMLSocket类和二进制套接字连接的Socket类。对于我来说如果服务器能发送XML数据过来当然是最好的,但可惜服务器是传输十六进制的数据的。相对XMLSocket来说,Socket数据处理更为底层,可操控范围更大,但难度也较大。

  对于实时传输数据有几大有解决的问题,如何持续正确连接,如何处理粘包,如何缓存数据等。正确连接,可以采用类似三次握手原则,服务端向服务器发起连接请求,服务器接收后返回一个验证码,客服端接收到后确认可以进行连接,然后后向服务器发回一个指定的数据,服务器确认了数据的正确性再发送指令确认客服端可以连接了。

  Flash的Socket连接是基于TCP的,所以不存在掉包的情况,最要是如何解决粘包或断包。从网上看到一些解决法案是服务器发送的数据在包头上加上数据长度信息,当客服端接收到数据包,先读取信息头,读取指示后面的数据有多大。如果已经读了信息头,则看能不能收到满足条件的字节数,若数据流里的数据满足条件,开始读数据,如果数据流里还未满足读取数据条件,则继续读取数据。至于如何缓存数据,最简单的就是将数据保存到数组中,不过如何在适当的时候读取数组中的数据还未想到较好的办法。

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; //收到的消息最大长度
         private var msgLen:int; //消息长度
         private var headLen:int; //消息头长度
         private var isReadHead:Boolean; //是否已经读了消息头
         private var bytes:ByteArray; //所读数据的缓冲数据,读出的数据放在这里
         
         public function SocketExample()
         {
             isReadHead = true;
             headLen = 2; //2个字节
             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 == "重新连接")
             {
                 //注册socket事件
                 configureListeners();
                 //进行socket连接
                 connectToSocketServer();
             }
             if (btnConnect.label == "关闭连接")
             {
                 if (socket.connected)
                 {
                     socket.close();
                     btnConnect.label = "连接";
                     pringMessage("客服端已关闭连接");
                 }
             }
         }
         
         /**
          * 连接socket服务器
          */
         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 = "关闭连接";
             pringMessage("连接成功" + "\n" + "connectHandler: " + event + "\n");
             btnSend.addEventListener(MouseEvent.CLICK, btnHandler);
             trace("connectHandler: " + event);
             trace(txtRead.text);
         }
         
         /**
          * 向服务器发送数据
          */
         private function sendRequest():void
         {
             trace("sendRequest");
             response = "";
             //发送内容
             writeln("GET /");
         }
         
         private function writeln(str:String):void
         {
             str += txtSend.text + "\n";
             if (socket.connected)
             {
                 try
                 {
                     //将UTF-8字符串写入套接字
                     socket.writeInt(int(str));
                     txtRead.text += "发送数据的数据:" + str;
                     socket.flush();
                 }
                 catch (error:IOError)
                 {
                     pringMessage("socket.flush error\n" + error);
                 }
             }
             else
             {
                 //进行socket连接
                 connectToSocketServer();
             }
         }
         
         /**
          * 接收数据,并读取
          */
         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);
                 //遍历数据包
                 while (socket.bytesAvailable)
                 {
                     var data:int = socket.readByte();
                     trace(data);
                 }
                 txtRead.text += "接收的数据:" + str + "\n";
             }
             catch (error:IOError)
             {
                 pringMessage("当socket已关闭而去读取时引发I/O 异常\n" + "socket.read error\n" + error);
             }
             catch (error:EOFError)
             {
                 pringMessage("没有数据可读而读取时引发EOF异常\n" + "socket.read error\n" + error);
             }
         
         }
         
         /**
          * 解析网络数据流
          * 根据信息头长度读取数据
          */
         private function parseNetData():void
         {
             //如果需要读信息头
             if (isReadHead)
             {
                 if (socket.bytesAvailable >= headLen)
                 {
                     //读出指示后面的数据有多大
                     msgLen = socket.readShort();
                     isReadHead = false;
                 }
             }
             //如果已经读了信息头,则看能不能收到满足条件的字节数
             if (!isReadHead && msgLen <= msgLenMax)
             {
                 //如果为0,表示收到异常消息
                 if (msgLen == 0)
                 {
                     //一般消息长度为0的话,表示与服务器出了错,或者即将被断开等,通知客户端,进行特别处理
                     return;
                 }
                 //数据流里的数据满足条件,开始读数据
                 if (socket.bytesAvailable >= msgLen)
                 {
                     //指针回归
                     bytes.position = 0;
                     //取出指定长度的网络字节
                     socket.readBytes(bytes, 0, msgLen);
                     isReadHead = true;
                 }
             }
             //如果数据流里还满足读取数据条件,继续读取数据
             if (socket.bytesAvailable >= headLen)
             {
                 parseNetData();
             }
         }
         
         /**
          * socket服务器关闭连接
          */
         private function closeHandler(event:Event):void
         {
             btnConnect.label = "重新连接";
             pringMessage("socke服务器已关闭\n" + "closeHandler: " + event);
             trace("closeHandler: " + event);
         }
         
         private function ioErrorHandler(event:IOErrorEvent):void
         {
             trace("ioErrorHandler: " + event);
             pringMessage("输入/输出错误并导致发送或加载操作失败\n" + "ioErrorHandler: " + event);
         }
         
         private function securityErrorHandler(event:SecurityErrorEvent):void
         {
             trace("securityErrorHandler: " + event);
             pringMessage("尝试连接到调用方安全沙箱外部的服务器或端口号低于 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
      * 来源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
         {
         }
     }
 }

====================================分割线================================

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-09-20 12:03:09

日立扶梯项目功能测试的相关文章

Etrion与日立获信托银行融资建立13.2MW光伏项目

2016年11月21日,瑞士独立太阳能发电厂Etrion公司宣布与日本三井住友信托银行有限公司签署项目融资协议,用于建设位于日本石川县的13.2MW Komatsu太阳能光伏项目. 此太阳能光伏电厂建于日本石川县,预计将于2017年2月开始施工,预计将在2018年第二季度全面投入运行. Etrion首席执行官Marco A. Northland评论道:"我很高兴地宣布13.2MW Komatsu项目签署了3300万美元的项目融资,它是我们在日本建立的第四个公用事业规模太阳能项目." 此

日立计划强化国内外市场“大数据”业务

据日本共同社6月6日报道,日立制作所6日表示将强化"大数据"业务,包括海外市场在内,到http://www.aliyun.com/zixun/aggregation/37255.html">2015年力争销售额达到1500亿日元(约合9001.html">人民币93亿元)."大数据"包括了由IT收集的汽车行驶记录.零售业购买动向等庞大信息,日立将对此进行分析. 日立计划强化国内外市场"大数据"业务 该业务的指挥部&

日立数据任命四大高管四处挖人拓展存储市场

       2月24日消息,WatchStor获悉,日立数据系统公司日前任命四大总裁,任命Eric-Jan Schmidt和Asim Zaheer担任市场高级管理人员,任命Scanlon Putegnat和Miklos Sandorfi担任技术主管.四位副总裁分别来自电信.存储.营销等领域,此次日立数据积极挖掘人才致力于保持其作为行业创新者和技术领先者的地位. 日立数据系统公司负责全球市场与业务开发的高级副总裁Brian Householder表示:"我们的目标是进一步增强日立数据系统作为存储

消息称日立与三菱重工商讨合并事宜

新浪科技讯 北京时间8月4日晚间消息,三位知情人士称,日立和三菱重工正在商讨合并事宜.如果两家公司成功合并,将成为日本国内规模最大的合并交易. 东京MU Investments公司首席基金经理Kiyoshi Noda称:"如果合并消息属实,那么对日本工业是一个利好消息,因为今后在竞购国外基础设施项目时,就不会再自相残杀了.这将增加日本企业的机会,从而推动日本经济的发展." 知情人士称,日立和三菱重工高管主要讨论在下一代能源和智能网格(smart grids)等领域进行合并.该消息经媒体

日立数据系统亚太地区年度CIO峰会召开

 [51CTO独家特稿]2008 年11月6日,日立公司全资子公司.服务导向型存储解决方案的唯一提供商日立数据系统公司今天在2008 IT 创意大奖赛的盛大颁奖典礼上宣布了本地和地区的最终获奖者.本次大赛的揭晓和日立数据系统年度亚太区 CIO 峰会一起为来自亚太区的IT高管们提供了一个交流和学习的机会. 日立数据系统公司副总裁兼总经理Randy DeMont 今年8月启动的首届日立数据系统IT 创意大奖赛为亚太区的诸多领先企业提供了一个独特的平台,展示其所做出的科技创新,从而推动业务健康发展.竞

戴尔EMC、日立数据系统和NetApp现已出货博科第六代光纤通道方案

赛迪网讯博科今天宣布其第六代光纤通道存储网络解决方案延续良好的发展态势,将通过包括戴尔EMC.富士通和NetApp等在内的OEM合作伙伴销售.此前,日立数据系统已经从7月份开始出货博科第六代导向器.刀片和交换机.这进一步体现了光纤通道作为关键企业存储首选协议的地位. Gartner在2016年6月发布了名为<存储协议的未来>报告,其中提到:"随着高吞吐量.固态和闪存存储的普及,存储网络正在成为优先投资的项目-存储性能瓶颈正在从阵列转向存储网络.因此,光纤通道在未来十年仍将是数据中心存

日立公司宣布将在中国建立两大数据中心

来自国外媒体的消息,日立公司当地时间周四表示,将在中国建立两大数据中心,以积极推动其大型云计算项目和市场软件项目的发展,并力争整合整个城市基础设施的数据. 日立公司表示,将在日后着重销售以云计算为基础的系统,整合与分析公路.航运.能源网格和大批量运输等不同来源收集到的数据. 日立公司平台业务负责人Kaichiro Sakuma表示:"目前这些系统都是独立存在的,比如列车控制系统或公司管理系统,但我们希望可以使用云技术来将这些系统连接到一起,这是其他IT厂商所不能提供的技术." 日立表示

日立拳击绿金

□ 记者 张娅 作为较早捕捉到中国节能环保商机的企业之一,日立在中国获得的第二个国家级项目正全面展开.6月20日,日立与31家宁波市企业一并签署了"关于推进节能诊断国际合作的意向协议".作为2008年5月日立与国家发改委签订<中国中小企业节能减排示范项目>协议后具体落实的案例,宁波项目由日立与宁波市共同推进.中国日立集团总代表大野信行解释道:"中小企业分布零散,如果每个都单独签约会比较繁复,所以我们在宁波市政府牵头的情况下做这样一个项目,不仅对中小企业有好处,对日

消息称日立与三菱重工或将合并 正展开磋商

8月5日消息,据路透社报道,三位http://www.aliyun.com/zixun/aggregation/18501.html">消息人士透露,日立公司和三菱重工业公司正就合并一事展开磋商.如果两家公司成功合并,那么这将成为日本最大的合并交易案. 传统上来说,在日本,合并通常被视为将要破产的公司在迫不得已才诉诸的手段.此前,日本公司大体上都试图避免战略性合并.此番日本最古老﹑最有声誉的两家企业集团的合并,将预示着日本公司开始将战略合并作为压缩成本﹑抵抗强势日元和形成更具竞争性规模优势