日立扶梯项目功能测试

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

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

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

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

 

  1 package
  2 {
  3     import flash.display.Sprite;
  4     import flash.net.Socket;
  5     import flash.events.IOErrorEvent;
  6     import flash.events.SecurityErrorEvent;
  7     import flash.events.ProgressEvent;
  8     import flash.events.Event;
  9     import flash.errors.IOError;
 10     import flash.events.MouseEvent;
 11     import flash.errors.EOFError;
 12     import flash.system.Security;
 13     import flash.utils.ByteArray;
 14     
 15     /**
 16      *
 17      * @author whk
 18      */
 19     public class SocketExample extends Sprite
 20     {
 21         private var targetServer:String = "192.168.0.68"; //连接ip地址
 22         private var port:uint = 9991; //连接端口        
 23         private var socket:Socket;
 24         private var str:String;
 25         private var response:String;
 26         private var msgLenMax:int; //收到的消息最大长度
 27         private var msgLen:int; //消息长度
 28         private var headLen:int; //消息头长度
 29         private var isReadHead:Boolean; //是否已经读了消息头
 30         private var bytes:ByteArray; //所读数据的缓冲数据,读出的数据放在这里
 31         
 32         public function SocketExample()
 33         {
 34             isReadHead = true;
 35             headLen = 2; //2个字节
 36             msgLenMax = 4028;
 37             bytes = new ByteArray();
 38             //Security.loadPolicyFile("socket://"+targetServer+":"+port);
 39             socket = new Socket();
 40             btnSend.enabled = false;
 41             btnConnect.addEventListener(MouseEvent.CLICK, btnHandler);
 42         }
 43         
 44         /**
 45          * 处理按钮事件
 46          */
 47         private function btnHandler(event:MouseEvent):void
 48         {
 49             switch (event.target.name)
 50             {
 51                 case "btnConnect": 
 52                     btnLabel();
 53                     break;
 54                 case "btnSend": 
 55                     sendRequest();
 56                     break;
 57             }
 58         }
 59         
 60         private function btnLabel():void
 61         {
 62             if (btnConnect.label == "连接" || btnConnect.label == "重新连接")
 63             {
 64                 //注册socket事件
 65                 configureListeners();
 66                 //进行socket连接
 67                 connectToSocketServer();
 68             }
 69             if (btnConnect.label == "关闭连接")
 70             {
 71                 if (socket.connected)
 72                 {
 73                     socket.close();
 74                     btnConnect.label = "连接";
 75                     pringMessage("客服端已关闭连接");
 76                 }
 77             }
 78         }
 79         
 80         /**
 81          * 连接socket服务器
 82          */
 83         private function connectToSocketServer():void
 84         {
 85             try
 86             {
 87                 socket.connect(targetServer, port);
 88             }
 89             catch (error:SecurityError)
 90             {
 91                 pringMessage("SecurityError: " + error);
 92             }
 93         
 94         }
 95         
 96         private function configureListeners():void
 97         {
 98             socket.addEventListener(Event.CONNECT, connectHandler);
 99             socket.addEventListener(Event.CLOSE, closeHandler);
100             socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
101             socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
102             socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
103         }
104         
105         /**
106          * 连接成功
107          */
108         private function connectHandler(event:Event):void
109         {
110             btnSend.enabled = true;
111             btnConnect.label = "关闭连接";
112             pringMessage("连接成功" + "\n" + "connectHandler: " + event + "\n");
113             btnSend.addEventListener(MouseEvent.CLICK, btnHandler);
114             trace("connectHandler: " + event);
115             trace(txtRead.text);
116         }
117         
118         /**
119          * 向服务器发送数据
120          */
121         private function sendRequest():void
122         {
123             trace("sendRequest");
124             response = "";
125             //发送内容
126             writeln("GET /");
127         }
128         
129         private function writeln(str:String):void
130         {
131             str += txtSend.text + "\n";
132             if (socket.connected)
133             {
134                 try
135                 {
136                     //将UTF-8字符串写入套接字
137                     socket.writeInt(int(str));
138                     txtRead.text += "发送数据的数据:" + str;
139                     socket.flush();
140                 }
141                 catch (error:IOError)
142                 {
143                     pringMessage("socket.flush error\n" + error);
144                 }
145             }
146             else
147             {
148                 //进行socket连接
149                 connectToSocketServer();
150             }
151         }
152         
153         /**
154          * 接收数据,并读取
155          */
156         private function socketDataHandler(event:ProgressEvent):void
157         {
158             trace("socketDataHandler: " + event);
159             readResponse();
160         }
161         
162         private function readResponse():void
163         {
164             try
165             {
166                 //parseNetData();
167                 var str:String = socket.readUTFBytes(socket.bytesAvailable);
168                 response += str;
169                 trace(response);
170                 //遍历数据包
171                 while (socket.bytesAvailable)
172                 {
173                     var data:int = socket.readByte();
174                     trace(data);
175                 }
176                 txtRead.text += "接收的数据:" + str + "\n";
177             }
178             catch (error:IOError)
179             {
180                 pringMessage("当socket已关闭而去读取时引发I/O 异常\n" + "socket.read error\n" + error);
181             }
182             catch (error:EOFError)
183             {
184                 pringMessage("没有数据可读而读取时引发EOF异常\n" + "socket.read error\n" + error);
185             }
186         
187         }
188         
189         /**
190          * 解析网络数据流
191          * 根据信息头长度读取数据
192          */
193         private function parseNetData():void
194         {
195             //如果需要读信息头
196             if (isReadHead)
197             {
198                 if (socket.bytesAvailable >= headLen)
199                 {
200                     //读出指示后面的数据有多大
201                     msgLen = socket.readShort();
202                     isReadHead = false;
203                 }
204             }
205             //如果已经读了信息头,则看能不能收到满足条件的字节数
206             if (!isReadHead && msgLen <= msgLenMax)
207             {
208                 //如果为0,表示收到异常消息
209                 if (msgLen == 0)
210                 {
211                     //一般消息长度为0的话,表示与服务器出了错,或者即将被断开等,通知客户端,进行特别处理
212                     return;
213                 }
214                 //数据流里的数据满足条件,开始读数据
215                 if (socket.bytesAvailable >= msgLen)
216                 {
217                     //指针回归
218                     bytes.position = 0;
219                     //取出指定长度的网络字节
220                     socket.readBytes(bytes, 0, msgLen);
221                     isReadHead = true;
222                 }
223             }
224             //如果数据流里还满足读取数据条件,继续读取数据
225             if (socket.bytesAvailable >= headLen)
226             {
227                 parseNetData();
228             }
229         }
230         
231         /**
232          * socket服务器关闭连接
233          */
234         private function closeHandler(event:Event):void
235         {
236             btnConnect.label = "重新连接";
237             pringMessage("socke服务器已关闭\n" + "closeHandler: " + event);
238             trace("closeHandler: " + event);
239         }
240         
241         private function ioErrorHandler(event:IOErrorEvent):void
242         {
243             trace("ioErrorHandler: " + event);
244             pringMessage("输入/输出错误并导致发送或加载操作失败\n" + "ioErrorHandler: " + event);
245         }
246         
247         private function securityErrorHandler(event:SecurityErrorEvent):void
248         {
249             trace("securityErrorHandler: " + event);
250             pringMessage("尝试连接到调用方安全沙箱外部的服务器或端口号低于 1024 的端口\n" + "securityErrorHandler: " + event);
251         }
252         
253         /**
254          * 将消息打印到屏幕
255          * @param m:打印的消息
256          */
257         private function pringMessage(m:String = null):void
258         {
259             txtError.visible = true;
260             if (m == null)
261             {
262                 txtError.text = "";
263                 txtError.visible = false;
264                 return;
265             }
266             if (txtError.text == null)
267             {
268                 txtError.text = "";
269                 txtError.visible = false;
270             }
271             txtError.text = m;
272         }
273     
274     }
275 }

  Socket三次握手例子:

 1 package 
 2 {
 3     import flash.display.Sprite;
 4     import flash.events.ProgressEvent;
 5     import flash.net.Socket;
 6     import flash.utils.ByteArray;
 7     /**
 8      *
 9      * 三次握手连接socket
10      * 来源socket编程
11      */
12     public class SocketHandshake extends Sprite
13     {
14         public const DETERMINE_VERSION:int = 0;
15         public const RECEIVE_CHALLENGE:int = 1;
16         public const NORMAL:int = 2;
17         private var stateMap:Object;
18         private var currentState:int;
19         private var socket:Socket;
20         public function SocketHandshake( )
21         {
22             stateMap = new Object( );
23             stateMap[DETERMINE_VERSION] = readVersion;
24             stateMap[RECEIVE_CHALLENGE] = readChallenge;
25             stateMap[NORMAL] = readNormalProtocol;
26             currentState = DETERMINE_VERSION;
27             socket = new Socket( );
28             socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );
29             socket.connect( "localhost", 9000 );
30             trace(currentState);
31         }
32         private function onSocketData( event:ProgressEvent ):void
33         {
34             trace(currentState);
35             var processFunc:Function = stateMap[currentState];
36             processFunc( );
37         }
38         private function readVersion( ):void
39         {
40 
41             try
42             {
43                 var version:int = socket.readInt();
44                 trace(version);
45             }
46             catch (error:Error)
47             {
48                 trace("error:"+error);
49             }
50             currentState = RECEIVE_CHALLENGE;
51             socket.writeInt( version );
52             socket.flush( );
53         }
54         private function readChallenge( ):void
55         {
56             var bytes:ByteArray = new ByteArray( );
57             socket.readBytes( bytes, 0, 8 );
58             currentState = NORMAL;
59             socket.writeBytes( bytes );
60             socket.flush( );
61         }
62         private function readNormalProtocol( ):void
63         {
64         }
65     }
66 }
posted @ 2012-05-28 21:17  FlashHK  阅读(441)  评论(0编辑  收藏  举报