flash发起socket通讯的三个过程:
1、当封装在页面的flash发起socket通讯请求的时候会寻找服务器端843端口, 获取crossdomain.xml文件。
2、当服务器没有开启843的时候,flash player会检查发起请求的swf文件中有没有使用Security.loadPolicyFile(xmlsocket://127.0.0.1:4299)
来加载策略文件crossdomain.xml。
3、如果没有就会看这个发起请求的swf要连接的目标端口有没有策略文件。
如果上述三个步骤都没有找到策略文件,那么出现连接失败并出现错误提示:
[SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048"]
新版的flash player,当flash文件要进行socket通讯的时候,需要向服务器端 获取crossdomain.xml文件,如果找不到就会出现上述问题。
(老版的flash player无论你采用的是http请求方式或者xmlsocket socket方式, 他们都共用一个安全策略文件,这个策略文件只要你放在主域的目录下就行,
而新版的要求,如果你使用http请求方式需要把策略文件放在目录下面,如果你使用的socket请求方式就必须通过socket端口来接收这个策略文件。
其对应的调用的方式为:
http请求:Security.loadPolicyFile("http://www.xxx.com/crossdomain.xml");
socket或xmlsocket请求:Security.loadPolicyFile("xmlsocket://www.xxx.com:port");)
三种方法:
一、使用默认843端口
flash player在你的socket.connect(address,port);运行之前,会按照三个过程向你的socket 服务器的843端口发送一个字符串 "<policy-file-request/>" ,
这个时候如果你有一个服务器在监听843端口那么受到这个字符串之后,直接按照xml格式发挥策略文件就解决了。
二、使用自定义端口(推荐使用)
当然你也可以自己设置一个端口,不过这个时候不能用Http方式,而要用xmlsocket方式。相当于自动帮你新建一个xmlsocket对象,
然后连接你指定的主机和端口, 比如你想用1234端口可以在你的flash里面加这一句Security.loadPolicyFile("xmlsocket://www.xxx.com:1234")
需要注意的是这一句要加在你的socket.connect()前面。
三、代码发送策略文件。
在你的socket连接端口监听这个请求,比如你用的是socekt.connect("127.0.0.1",3333);
那么在你的服务器加一段接受字符串"<policy-file-request/>"的代码,当接收到这个字符串 的时候将策略文件按照xml格式发到客户端。
1、针对web应用的策略文件
示列为策略文件允许访问源自:*game.com和192.168.1.1的swf文件
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*.game.com" />
<allow-access-from domain="192.168.1.1" />
</cross-domain-policy>
注意事项:
默认情况下,策略文件必须命名为 crossdomain.xml,并且必须位于服务器的根目录中。但是,SWF 文件可以通过调用
Security.loadPolicyFile() 方法检查是否为其它名称或位于 其它目录中。跨域策略文件仅适用于从其中加载该文件的目录
及其子目录。因此,根目录中的策略文件适用于整个服务器, 但是从任意子目录加载的策略文件仅适用于该目录及其子目录。
2、针对socket的策略文件
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<allow-access-from domain="*" to-ports="507" />
<allow-access-from domain="*.example.com" to-ports="507,516" />
<allow-access-from domain="*.example2.com" to-ports="516-523" />
<allow-access-from domain="www.example3.com" to-ports="*" />
</cross-domain-policy>
这个策略文件是指定允许哪些域的主机通过哪些端口链接。
java socket服务端:
安全策略服务器: public class SecurityServer { private int count = 0; public String xml = ""; private InputStream is; private OutputStream os; public void start() throws Exception { xml += "<cross-domain-policy>"; xml += "<allow-access-from domain=\"*\" to-ports=\"*\" />"; xml += "</cross-domain-policy>"; ServerSocket serverSocket = new ServerSocket(4299); System.out.println("等待用户连接``并发送策略文件``````"); while (true) { try { Socket socket = serverSocket.accept(); count++; this.is = socket.getInputStream(); this.os = socket.getOutputStream(); byte[] temp = new byte[300]; this.is.read(temp); this.os.write(this.xml.getBytes("utf-8")); this.os.flush(); this.os.close(); this.is.close(); socket.close(); } catch (Exception e) { System.out.println("服务器发生异常"); } } } public static void main(String[] args) { try { new SecurityServer().start(); } catch (Exception e) { System.out.println("Socket发生异常:" + e); } } }
主连接服务器: public class ServerJava { private int count =0; public void start() throws Exception { ServerSocket serverSocket = new ServerSocket(4399); System.out.println("等待用户连接````````"); while (true) { try { Socket socket = serverSocket.accept(); count++; System.out.println("连接成功``数量: `````"+count); ServerThread thread = new ServerThread(socket); thread.start(); } catch (Exception e) { System.out.println("服务器发生异常"); } } } public static void main(String[] args) { try { new ServerJava().start(); } catch (Exception e) { System.out.println("Socket发生异常:" + e); } } }
服务端读取客户端数据: public class ServerThread extends Thread { private Socket socket; private BufferedReader input; private PrintWriter output; private OutputStream os; private InputStream is; public ServerThread(Socket socket) { this.socket = socket; } public void run() { System.out.println("---------------启动一个线程-----------------"); try { this.os = this.socket.getOutputStream(); this.is = this.socket.getInputStream(); byte[] temp = new byte[1000]; int len = 0; StringBuffer msg = new StringBuffer(); while ((len = this.is.read(temp)) > 0) { msg.append(new String(temp, 0, len,"UTF-8")); if(len<1000){ this.os.write(msg.toString().getBytes("UTF-8")); this.os.flush(); msg = new StringBuffer(); } } } catch (Exception e) { System.out.println("子线程发生异常"); try { input.close(); output.close(); } catch (Exception ex) { System.out.println("关闭资源发生异常"); } System.out.println("子线程结束了"); } } }
as3客户单端代码:
package { import flash.net.Socket; import flash.events.ProgressEvent; import flash.events.Event; import flash.utils.ByteArray; import flash.display.Sprite; import flash.system.Security; import flash.text.TextField; import flash.events.MouseEvent; public class ClientSocket extends Sprite { private var count:uint=0; private var clientSocket:Socket; private var readBytes:ByteArray = new ByteArray(); private var writeBytes:ByteArray = new ByteArray(); public function ClientSocket() { conn.addEventListener(MouseEvent.CLICK,connServer); send.addEventListener(MouseEvent.CLICK,sendToServer); } private function connServer(evt:MouseEvent):void { clientSocket = new Socket(); Security.allowDomain("*"); Security.loadPolicyFile("xmlsocket://127.0.0.1:4299") clientSocket.connect("127.0.0.1",4399); clientSocket.addEventListener(Event.CONNECT,successConn); clientSocket.addEventListener(ProgressEvent.SOCKET_DATA,reviceData); } private function successConn(evt:Event):void { count++; dyText.text="连接成功"+count+"\n"; } private function sendToServer(evt:Event):void { var charContext=inputText.text; dyText.text=dyText.text+charContext+"\n"; //utf-8转码 clientSocket.writeUTFBytes(charContext); clientSocket.flush(); } private function reviceData(evt:Event):void { trace(totalLen+"======revice message==============="); var totalLen:uint=clientSocket.bytesAvailable; server.text=clientSocket.readUTFBytes(totalLen); } } }