使用XMLSocket在Flash和本地程序之间进行通讯

在实际应用中经常会用到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#服务器端代码:


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端代码:


<?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客户端的上传貌似就用这个做的?总之应用可能比较广啦。

相关文章
相关标签/搜索