在实际应用中经常会用到flash页面和本地exe程序或者ActiveX程序进行交互的情况。目前有两种方法:
1. flash <-> javascript <-> activex
这种应用中,本地exe程序必须是一个进城外的com控件,不仅制作成本高而且代码间的耦合度高。
2. flash <-> XMLSocket <-> exe
这种应用中,本地exe程序比较独立,flash和exe程序之间可以采用socket通讯的方式进行。本文详述这种方法的实现。
既然是Socket通讯,就必须有一个server和一个client。本文采用C#的TCPServer作server端简单范例,其他语言的程序类似。而client端则是flash的XMLSocket应用。
采用这种方法的关键是XMLSocket的安全策略检测。总结一下XMLSocket的安全策略检测,检测过程为:
1,首先检测目标服务器的843端口是否提供安全策略
2,如果843端口没有检测到策略,则检测actionscript是否使用了
Security.loadPolicyFile(xmlsocket://)
手段提供安全策略,如果还没检测到,则使用第3步检测
3,检测目标服务器目标端口是否提供安全策略
可以参考这篇文章,有策略检测过程详述及Linux下Python实现的例子。
本文直接采用目标服务器端口提供安全策略的方式。
C#服务器端代码:
TCP Server端
TcpListener server = null;
try
{
// Set the TcpListener on port 13000.
Int32 port = 13000;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
String xml = "<?xml version=\"1.0\"?>";
xml += "<cross-domain-policy>";
xml += @"<site-control permitted-cross-domain-policies=""all""/>";
xml += @"<allow-access-from domain=""*"" to-ports=""*"" />";
xml = xml + "</cross-domain-policy>\0";
// Enter the listening loop.
while (true)
{
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
try
{
Console.Write("Waiting for a connection ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
data = null;
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.UTF8.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
// Process the data sent by the client.
data = data.ToLower();
byte[] msg = null;
if (data.Equals("<policy-file-request/>\0"))
{
msg = System.Text.Encoding.UTF8.GetBytes(xml);
// Send back a response.
stream.Write(msg, 0, msg.Length);
Console.WriteLine("Sent: {0}", xml);
stream.Flush();
//break;
}
else
{
msg = System.Text.Encoding.UTF8.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
Console.WriteLine("Sent: {0}", data);
}
}
}
catch (Exception error)
{
Console.WriteLine("Exception: {0}", error);
continue;
}
finally
{
client.Close();
}
}
}
catch (SocketException err)
{
Console.WriteLine("SocketException: {0}", err);
}
finally
{
// Stop listening for new clients.
server.Stop();
}
代码比较烂,将就看。基本就是echo的功能啦。
实际应用中受到TCPClient连接应该启动工作线程进行实际操作。如果受到的是"<policy-file-request/>/0"策略请求,则工作线程可关闭连接,退出。flash在无论是否收到策略文件,都会关闭当前连接重新建立连接。另外,我在调试时很郁闷的一件事情是:当server端在flash请求策略时停留过长时间,估计也就10秒左右(具体时间没认真看),flash就会抛出SecurityError错误事件。所以尽量不要采用跟踪的调试(可以trace什么的嘛)。
再看Flex端代码:
Flex Client
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300" creationComplete="OnCreationComplete()">
<mx:Script>
<![CDATA[
private var xmlsock:XMLSocket = null;
private function OnCreationComplete():void
{
xmlsock = new XMLSocket()
xmlsock.connect("127.0.0.1", 13000);
xmlsock.addEventListener(DataEvent.DATA, OnData);
xmlsock.addEventListener(IOErrorEvent.IO_ERROR, OnIOError);
xmlsock.addEventListener(SecurityErrorEvent.SECURITY_ERROR, OnSecurityError);
}
private function OnSend():void
{
xmlsock.send(this.MessageTextArea.text);
}
private function OnIOError(event:IOErrorEvent):void
{
this.MessageReturnText.text = event.text;
}
private function OnData(event:DataEvent):void
{
var retMessage:String = "[" + event.type + "] " + event.data;
this.MessageReturnText.text = retMessage;
}
private function OnSecurityError(event:SecurityErrorEvent):void
{
this.MessageReturnText.text = event.text;
}
]]>
</mx:Script>
<mx:Label x="49" y="17" text="Message:"/>
<mx:TextArea id="MessageTextArea" x="116" y="17" width="201" height="58"/>
<mx:Button x="263" y="81" label="Send" click="OnSend()"/>
<mx:Label x="49" y="100" text="Messages from Server:"/>
<mx:Text id="MessageReturnText" x="116" y="126" width="201" height="72" text="123456"/>
</mx:Application>
代码没什么好解释的,很清楚嘛,就这么用。
Youtube带exe客户端的上传貌似就用这个做的?总之应用可能比较广啦。