ActionScript 3的HTTPTunnel的实现

ActionScript 3Adobe公司开发的用于编写Flash的脚本语言。Adobe新推出的Adobe FlexRich Internet Application开发平台同样支持Action ScriptActionScript编写的Flex Data Service提供了丰富的数据处理功能,也包括实现了通过建立HTTPChannel的数据实时更新功能,例如聊天室,股市行情等。本文将使用ActionScript 3.0编写HTTPTunnel Client取代Flex Data ServiceHTTPChannel 用开源的Java HTTPTunnel作为Server,实现数据实时更新。

1 架构

<group id="_x0000_s1026" style="WIDTH: 252.1pt; HEIGHT: 161.95pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line" coordsize="4291,2776" coordorigin="2279,5367" editas="canvas"><lock aspectratio="t" v:ext="edit"></lock><shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_s1027" style="LEFT: 2279px; WIDTH: 4291px; POSITION: absolute; TOP: 5367px; HEIGHT: 2776px" o:preferrelative="f" type="#_x0000_t75"><font size="3"><fill o:detectmouseclick="t"></fill><path o:connecttype="none" o:extrusionok="t"></path><lock v:ext="edit" text="t"></lock></font></shape><shapetype id="_x0000_t202" path="m,l,21600r21600,l21600,xe" o:spt="202" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><path o:connecttype="rect" gradientshapeok="t"></path></shapetype><shape id="_x0000_s1028" style="LEFT: 2739px; WIDTH: 1225px; POSITION: absolute; TOP: 6446px; HEIGHT: 771px" type="#_x0000_t202"><textbox inset="5.85pt,.7pt,5.85pt,.7pt"><table cellspacing="0" cellpadding="0" width="100%"><tbody><tr> <td style="BORDER-RIGHT: #ece9d8; BORDER-TOP: #ece9d8; BORDER-LEFT: #ece9d8; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent"> <div> <p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt"><span lang="EN-US" style="FONT-FAMILY: SimSun; mso-fareast-language: ZH-CN"><font size="3">Flash<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt"><span lang="EN-US" style="FONT-FAMILY: SimSun; mso-fareast-language: ZH-CN"><font size="3">Web Browser</font></span></p> </div> </td> </tr></tbody></table></textbox></shape><shape id="_x0000_s1029" style="LEFT: 5343px; WIDTH: 1227px; POSITION: absolute; TOP: 6446px; HEIGHT: 771px" type="#_x0000_t202"><textbox inset="5.85pt,.7pt,5.85pt,.7pt"><table cellspacing="0" cellpadding="0" width="100%"><tbody><tr> <td style="BORDER-RIGHT: #ece9d8; BORDER-TOP: #ece9d8; BORDER-LEFT: #ece9d8; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent"> <div> <p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt"><span lang="EN-US" style="FONT-FAMILY: SimSun; mso-fareast-language: ZH-CN"><font size="3">JHTTPTunnel <p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt"><span lang="EN-US" style="FONT-FAMILY: SimSun; mso-fareast-language: ZH-CN"><font size="3">Server<p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt"><span lang="EN-US"><p><font face="Century" size="3"></font></p></span></p> </div> </td> </tr></tbody></table></textbox></shape><shapetype id="_x0000_t38" filled="f" path="m,c@0,0@1,5400@1,10800@1,16200@2,21600,21600,21600e" o:spt="38" coordsize="21600,21600" o:oned="t"><formulas><f eqn="mid #0 0"></f><f eqn="val #0"></f><f eqn="mid #0 21600"></f></formulas><path o:connecttype="none" fillok="f" arrowok="t"></path><handles><h position="#0,center"></h></handles><lock v:ext="edit" shapetype="t"></lock></shapetype><shape id="_x0000_s1030" style="LEFT: 4653px; WIDTH: 1px; POSITION: absolute; TOP: 5145px; HEIGHT: 2604px; rotation: 270; flip: y" type="#_x0000_t38" adj="-7776000,-46412,63979200" o:connectortype="curved"><stroke endarrow="block"><font face="Century" size="3"></font></stroke></shape><shape id="_x0000_s1031" style="LEFT: 4653px; WIDTH: 1px; POSITION: absolute; TOP: 5916px; HEIGHT: 2604px; rotation: 90" type="#_x0000_t38" adj="7776000,-52765,-130075200" o:connectortype="curved"><stroke endarrow="block"><font face="Century" size="3"></font></stroke></shape><shape id="_x0000_s1032" style="LEFT: 3658px; WIDTH: 2604px; POSITION: absolute; TOP: 7680px; HEIGHT: 309px" stroked="f" filled="f" type="#_x0000_t202"><textbox inset="5.85pt,.7pt,5.85pt,.7pt"><table cellspacing="0" cellpadding="0" width="100%"><tbody><tr> <td style="BORDER-RIGHT: #ece9d8; BORDER-TOP: #ece9d8; BORDER-LEFT: #ece9d8; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent"> <div> <p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt"><span lang="EN-US" style="FONT-FAMILY: SimSun; mso-fareast-language: ZH-CN"><font size="3">3 HTTPHeader+Content Data</font></span></p> </div> </td> </tr></tbody></table></textbox></shape><shape id="_x0000_s1033" style="LEFT: 3964px; WIDTH: 1226px; POSITION: absolute; TOP: 5367px; HEIGHT: 617px" stroked="f" filled="f" type="#_x0000_t202"><textbox inset="5.85pt,.7pt,5.85pt,.7pt"><table cellspacing="0" cellpadding="0" width="100%"><tbody><tr> <td style="BORDER-RIGHT: #ece9d8; BORDER-TOP: #ece9d8; BORDER-LEFT: #ece9d8; BORDER-BOTTOM: #ece9d8; BACKGROUND-COLOR: transparent"> <div> <p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt"><span lang="EN-US" style="FONT-FAMILY: SimSun; mso-fareast-language: ZH-CN"><font size="3">1 Post <p></p></font></span></p> <p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt"><span lang="EN-US" style="FONT-FAMILY: SimSun; mso-fareast-language: ZH-CN"><font size="3">2 Get</font></span></p> </div> </td> </tr></tbody></table></textbox></shape><wrap type="none"></wrap><anchorlock></anchorlock></group>

1. Flash客户端连接HTTP Server并向HTTP Server发送Post命令。

2. Flash客户端连接HTTP Server并向HTTP Server发送Get命令。

3. HTTP ServerFlash不断发送遵循HTTP协议的数据,直到Flash客户端发送Close命令关闭连接。

4Flash客户端解析接受到的数据并更新界面。

ActionScript 3的HTTPTunnel的实现

2.实现

2.1 客户端

MXML-类似于XML语言,用于部署Flash界面,可被Flex SDK编译为Flash文件。

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="620" height="341"

creationComplete="Refresh()">

<mx:Script>

<![CDATA[

import org.colimas.http.*;

import mx.collections.*;

[Bindable]

public var initDG:ArrayCollection;

var host:String="localhost";

var hport:int=8888;

var jhtc:HttpTunnelClient=new HttpTunnelClient(host, hport);

private var DGArray:Array = [

{ corp:'IBM', last:79.99},

{ corp:'MS', last:30.99}];

private function Refresh():void {

trace("start...");

Data1.text="Started";

Data2.text="Yes!";

jhtc.setInBound(new InTunnelSocket());

jhtc.setOutBound(new OutTunnelSocket());

initDG=new ArrayCollection(DGArray);

jhtc.connect();

jhtc.Register(initDG);

jhtc.close();

var myTimer:Timer=new Timer(300);

myTimer.addEventListener("timer", timerHandler);

myTimer.start();

}

public function timerHandler(event:TimerEvent):void {

initDG.refresh();

}

]]>

</mx:Script>

<mx:Text x="41" y="38" text="Text1" width="62" height="28" id="Data1"/>

<mx:Text x="124" y="38" text="Text2" width="62" height="28" id="Data2"/>

<mx:DataGrid x="39" y="86" width="542" editable="false" id="Stock" dataProvider="{initDG}">

<mx:columns>

<mx:DataGridColumn headerText="Corp." dataField="corp"/>

<mx:DataGridColumn headerText="Last" dataField="last"/>

</mx:columns>

</mx:DataGrid>

</mx:Application>

界面显示如下:

<shape id="_x0000_i1026" style="WIDTH: 4in; HEIGHT: 239.25pt" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5C%E8%B6%99%E7%A3%8A%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image002.png"></imagedata></shape>

ActionScript 3的HTTPTunnel的实现

Refresh()函数实现数据刷新。org.colimas.http.HttpTunnelClient类用ActionScript语言编写,实现HTTPTunnel客户端,完成连接HTTPTunnel并接受数据任务。

org.colimas.http.HttpTunnelClient实现:

package org.colimas.http
{
 import flash.utils.ByteArray;
 import flash.errors.IOError;
 import mx.collections.ArrayCollection;
 
public class HttpTunnelClient extends HttpTunnel
 {
 static private var CONTENT_LENGTH:int=1024*10;
 
private var init:Boolean=false;
 private var closed:Boolean=false;
 
private var dest_host:String=null;
 private var dest_port:int=0;
 private var proxy:Proxy=null;
 
private var ib:InTunnel=null;
 private var ob:OutTunnel=null;
 
public function HttpTunnelClient( host:String, port:int){
 this.dest_host=host;
 this.dest_port=port;
 }
 /*传入用于界面显示的数据源*/

 public function Register(DGArray:ArrayCollection):void{
 this.ib.setData(DGArray);
 }
 
public function setProxy( host:String, port:int):void{
 this.proxy=new Proxy(host, port);
 }
 
public function connect():void{
 
if(ib==null){
 trace("InTunnel is not given");
 return;
 }
 ib.setHost(dest_host);
 ib.setPort(dest_port);
 ib.setProxy(proxy);
 
if(ob==null){
 trace("OutTunnel is not given");
 return;
 }
 ob.setHost(dest_host);
 ob.setPort(dest_port);
 ob.setProxy(proxy);
 ob.setContentLength(CONTENT_LENGTH);
 
getOutbound();
 getInbound();
 }
 /*数据发送OutTunnel类连接服务器端*/

 private function getOutbound():void{
 if(closed){
 trace("broken pipe");
 return;
 }
 ob.connect();
 }
 /*数据接受InTunnel连接服务器端*/

 private function getInbound():void{
 ib.connect();
 }
 
var buf_len:int=0;
 public function close():void{
 sendClose()
 ib.close()
 ob.close()
 closed=true;
 }
 
public function setInBound( ib:InTunnel):void { this.ib=ib; }
 public function setOutBound( ob:OutTunnel):void{ this.ob=ob; } 
}
}

数据发送OutTunnel类的实现

package org.colimas.http
{
 import flash.net.Socket;
 import flash.utils.ByteArray;
 import flash.events.DataEvent;
 import flash.events.Event;
 import flash.events.ErrorEvent;
 import flash.events.IOErrorEvent;
 import flash.events.ProgressEvent; 
public class OutTunnelSocket extends OutTunnel
 {
 static private var _rn:String="\r\n";
 
private var socket:Socket=null;
 private var request:String="/index.html?crap=1 HTTP/1.1"; 
public function OutTunnelSocket(){
 super();
 
}
 private function errorHandler(event:ErrorEvent):void
 {
 trace("[" + event.type + "] " + event.toString());
 
}
 
private function ioErrorHandler(event:IOErrorEvent):void
 {
 trace("[" + event.type + "] " + event.toString());
 }
 /*连接后发送POST请求*/

 private function connectHandler(event:Event):void {
 trace("Out[" + event.type + "] " + event.toString()); 
socket.writeUTF(request);
 socket.writeUTF(_rn);
 socket.writeUTF("Content-Length: "+getContentLength());
 socket.writeUTF(_rn);
 socket.writeUTF("Connection: close");
 socket.writeUTF(_rn);
 socket.writeUTF("Host: "+getHost()+":"+getPort());
 socket.writeUTF(_rn);
 socket.writeUTF(_rn);
 socket.flush();
 sendCount=getContentLength(); 
socket.writeByte(HttpTunnel.TUNNEL_OPEN);

 socket.writeByte(0);
 socket.writeByte(1);
 socket.writeByte(0);
 } 
public override function connect():void{
 close();
 var host:String=getHost();
 var port:int=getPort();
 

 var p:Proxy=getProxy();
 if(p==null){
 socket=new Socket(host, port);
 request="POST "+request;
 }
 else{
 var phost:String=p.getHost();
 var pport:int=p.getPort();
 socket=new Socket(phost, pport);
 request="POST http://"+host+":"+port+request;
 }
 socket.addEventListener(Event.CONNECT, connectHandler);
 socket.addEventListener(ErrorEvent.ERROR, errorHandler);
 socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
 }
 /*用于向Server发送命令*/

 public override function sendData(foo:ByteArray, s:int, l:int, flush:Boolean):void{
 if(l<=0) return;
 if(sendCount<=0){
 trace("1#");
 connect();
 </sp 

你可能感兴趣的:(socket,Flex,F#,Flash,actionscript)