1.问题描述:
将flash发布为html格式后,加载页面后,swf无法与服务器进行socket通信。Flash端显
示的错误为:
securityErrorHandler信息: [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048"] |
在服务器端显示的信息是由客户端尝试进行连接,但是无法接受数据。接受的数据显示为空。
2.问题原因:
当flash player升级到9.0.115.0之后,当flash文件要进行socket通信的时候,需要向服务
器端获取crossdomain.xml文件。在9.0.115.0之前的版本的flash是可以和socket进行正
常通信的。在升级后的版本后,就出现客户端无法连接服务器的现象。
3.flash发起socket通信的过程
当封装在页面的flash发起socket通信请求的时候会先寻找服务器端的843端口,获取
Crossdomain.xml文件,当服务器没有开启843的时候,flash会通过Security.loadPolicyFile
Security.loadPolicyFile("xmlsocket://192.168.1.100:844"); Security.loadPolicyFile("http://192.168.1.100:844"); |
的xmlsocket和http两种方式来读取Crossdomain.xml文件,如果还是无法读取该文件,则客户端会进行第三次尝试来检查服务器端是否提供了安全策略文件,当上述三个方法都无法成功的时候,客户端会拒绝连接,简单的可以归纳为一下三种方式:
1)首先检测目标服务器的843端口是否提供安全策略。
2) 如果1没有检测到策略,则检测actionscript是否使用了
Security.loadPolicyFile(“xmlsocket://”) 手 段提供安全策略,
如果还没检测到,则使用第3步检测。
3)检测目标服务器目标端口是否提供安全策略。
4.解决办法。
根据在页面flash发起socket的过程,我们可以寻找解决问题的办法,首先简单的办法,就是在服务器端编写好一个Crossdomain.xml文件,等待客户机的读取。客户端读取的时候就是按上面所说的办法来进行读取,但是这个测试我一直没有测试成功,所以就不多说了,如果谁测试成功了,希望能指点一下,下面我主要是介绍一下我的解决办法,思路如下:
1)在服务器端启动843端口,当客户端进行连接的时候,首先会向843端口发送<policy-
file-request/>信息来请求服务器来发送Crossdomain.xml的内容,注意此时发送的
是一个字符串数据,而不是一个xml文本,后面的代码示例中我会详细介绍。
2)当服务器接收到有客户端发送的<policy-file-request/>请求时,就会立即回复一
个包含有Crossdomain.xml配置信息的字符串。
3)Java代码如下:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket;
public class SecurityXMLServer implements Runnable {
private ServerSocket server; private BufferedReader reader; private BufferedWriter writer; private String xml;
public SecurityXMLServer() { String path = "policyfile文件路径"; //此处的换成相应的读取xml文档的方式如dom或sax //xml = readFile(path, "UTF-8"); /** 注意此处xml文件的内容,为纯字符串,没有xml文档的版本号 */ xml="<cross-domain-policy> " +"<allow-access-from domain=/"*/" to-ports=/"1025-9999/"/>" +"</cross-domain-policy> "; System.out.println("policyfile文件路径: " + path); System.out.println(xml);
//启动843端口 createServerSocket(843); new Thread(this).start(); }
//启动服务器 private void createServerSocket(int port) { try { server = new ServerSocket(port); System.out.println("服务监听端口:" + port); } catch (IOException e) { System.exit(1); } }
//启动服务器线程 public void run() { while (true) { Socket client = null; try { //接收客户端的连接 client = server.accept();
InputStreamReader input = new InputStreamReader(client.getInputStream(), "UTF-8"); reader = new BufferedReader(input); OutputStreamWriter output = new OutputStreamWriter(client.getOutputStream(), "UTF-8"); writer = new BufferedWriter(output);
//读取客户端发送的数据 StringBuilder data = new StringBuilder(); int c = 0; while ((c = reader.read()) != -1) { if (c != '/0') data.append((char) c); else break; } String info = data.toString(); System.out.println("输入的请求: " + info);
//接收到客户端的请求之后,将策略文件发送出去 if(info.indexOf("<policy-file-request/>") >=0) { writer.write(xml + "/0"); writer.flush(); System.out.println("将安全策略文件发送至: " + client.getInetAddress()); } else { writer.write("请求无法识别/0"); writer.flush(); System.out.println("请求无法识别: "+client.getInetAddress()); } client.close(); } catch (Exception e) { e.printStackTrace(); try { //发现异常关闭连接 if (client != null) { client.close(); client = null; } } catch (IOException ex) { ex.printStackTrace(); } finally { //调用垃圾收集方法 System.gc(); } } } }
//测试主函数 public static void main(String[] args) { new SecurityXMLServer(); } } |
5)最后讲一下crossdomain。Xml文件的配置方法:
<?xml version="1.0"?> <cross-domain-policy> <allow-access-from domain="服务器允许的客户端的域名或Ip(可以指定范围)" to-port=“服务器允许客户端访问的端口”/> </cross-domain-policy> |
例如想让域www.toplx.com,IP段在192.168.1.2----19.168.1.210段的客户来访问服务器的
2008,和2000--4000的端口,我们就可以这样配置。
<?xml version="1.0"?> <cross-domain-policy> <allow-access-from domain="www.toplx.com,192.168.1.2-192.168.210" to-port="2008,2000-4000"/> <!---如果想让所有的客户端访问服务器,则配置成如下 <allow-access-from domain="*" to-port="2008,2000-4000"/> --> </cross-domain-policy> |