AS3 + Java 端口号低于 1024 的 Socket 连接

原文:AS3 + Java: Socket connections to ports below 1024
翻译:dreamana.com

如今在很多人开始试验 AS3 的 Socket 类,在此之前我常看到有人说不能连接低于 1024 的端口。其实可以用一个特殊的 socket server 给 Flash Player 返回一个 cross domain policy 信息来让它连接上的,这就像在你的 Web 服务器上放置一个 cross-domain-policy 文件一样,只需多花一点点精力。

连接低于 1024 的端口会带来一些有趣的可能,例如开发能绕过防火墙通过 80 端口的多用户应用程序,编写你自己的电子邮件客户端、FTP 客户端等等网络客户端(这都不需要监听进来的连接的,所以就别想在 Flash 里 P2P 了)。Joa Ebert 已经写了个 Flash IRC 客户端 的例子。你也可以自己写一个代理来连接某服务器的某端口 …

下面是使 AS3 Socket 和 XMLSocket 连接一个低端口的方法,如网页服务器 80 端口。

AS3 commands

当你调用 AS3 的 Socket 类的 connect 方法的时候:

Actionscript:

    socket = new Socket();
    socket.connect("localhost", 80);

…Flash Player 会悄悄打开一个 Socket (上面的例子是 80 端口) 并发送出如下字符序列:

XML:

    <policy-file-request/> 

如果服务器回应一个 xml 文件格式的 policy 字符串,Flash Player 就会打开一个真正的 Socket 并把 Event.CONNECT 事件撤掉。要是没有 policy 字符串返回将会连接失败。

XML:

    <?xml version="1.0"?>
    <cross-domain-policy>
        <allow-access-from domain="*" to-ports="80" />
    </cross-domain-policy> 

现在你可能不想编辑你的 Web 服务器的源代码来让它回应 Flash Player 的 policy-请求。幸好 AS3 有一个命令可以使 Flash 连接到另一个端口去寻找 policy:

Actionscript: Security.loadPolicyFile(“xmlsocket://localhost:1008”);

这会使 Flash Player 在 1008 端口打开一个 Socket,发送一个 policy-请求并读取 policy-文件。若允许连接则毫不延误地在 80 端口打开所期望的 Socket 连接。

要注意的是,在低于 1024 端口读取 policy-文件只能够创建低于 1024 的连接。如果你的 policy-文件放到在某个大于 1024 的端口(譬如 8008)上服务,是不可以创建 1024 以下的连接的,就算 policy-文件这样写。

奇怪的是, Adobe’s DTD 定义 policy file 的结构 并没有提到 to-ports 属性,然而 Flash Player 却一定会读取它。

Java socket server

我写了一个简单的 Java 类,启动后就是一个 policy 服务器。默认是监听在 1008 端口,允许连接任意端口。这仅为了便于测试,公开运行时一定要更改。

你可以在这里 下载源代码 或者 下载可运行的 jar 文件

你只需安装了 Java-Runtime-Environment (可能你已经有了)并在命令行上输入 java -jar policyserver.jar

Flex example client

我还写了一个小例子,一个连接本地 Web 服务器的 AS/Flex 应用程序,发送一个 HTTP GET 命令并读取从 Web 服务器返回包含 HTTP 头部的信息。你可以当它是浏览器 ;) - 可惜它只能让你连接到带有 policy 服务器运行着的服务器。

你可以在这里 下载源代码 将它导入一个 Flex project 中并将 WebReader.as 设为 Default Application 即可。

Update 2011/07/28 补充:

843 是默认端口。如果你的服务端在接收到连接请求时候能够在 843 端口输出 cross-domain-policy,那么就不需要 Flash 客户端里面额外写代码,它会自动完成被授权访问的操作。