Erlang与Flash的Socket通讯-02
前一次实验,我使用的是本地swf文件,所以没有遇到安全沙箱问题,但在实际环境中我们的Flash文件是通过URL引用的,这时候Flash的Socket通讯会受到安全沙箱机制的限制。具体原理是:Flash在尝试向服务器A发起Socket连接前,会先尝试连接服务器A的843端口,求情一个xml格式的安全策略文件,该文件告诉Flash是否有权限向服务器A发起Socket连接。所以,我们需要在Erlang端增设一个守候在843端口的安全策略文件服务器。
此次实验的Erlang代码:
-module(server).
-export([start/1]).
-export([policy_file_server/0, policy_file_server_proc/1]).
-export([flash_socket_server/1, flash_socket_server_proc/1]).
start (Port) ->
??? spawn(?MODULE, policy_file_server, []),
??? spawn(?MODULE, flash_socket_server, [Port]).
%%------------------------------------------
%% Flash Policy File Server
%%------------------------------------------
policy_file_server () ->
??? {ok, LSock} = gen_tcp:listen(843, [binary, {packet, 0}, {active, false}]),
??? policy_file_server_accept(LSock).
policy_file_server_accept (LSock) ->
??? case gen_tcp:accept(LSock) of
??????? {ok, Sock} ->
??????????? spawn(?MODULE, policy_file_server_proc, [Sock]),
??????????? policy_file_server_accept(LSock);
??????? {error, Reason} ->
??????????? io:format("policy file server exit: ~s~n", [Reason]),
??????????? exit(Reason)
??? end.
policy_file_server_proc (Sock) ->
??? case gen_tcp:recv(Sock, 0) of
??????? {ok, _} ->
??????????? gen_tcp:send(Sock, <<
??????????????? "<?xml version="1.0"?>"
??????????????? "<cross-domain-policy>",
??????????????? "<allow-access-from domain="*" to-ports="*" />",
??????????????? "</cross-domain-policy>",0
??????????? >>);
??????? _ ->
??????????? ok
??? end,
??? gen_tcp:close(Sock).
%%------------------------------------------
%% Flash Socket Server
%%------------------------------------------
flash_socket_server (Port) ->
??? {ok, LSock} = gen_tcp:listen(Port, [list, {packet, 2}, {active, false}]),
??? flash_socket_server_accpet(LSock).
flash_socket_server_accpet (LSock) ->
??? case gen_tcp:accept(LSock) of
??????? {ok, Sock} ->
??????????? spawn(?MODULE, flash_socket_server_proc, [Sock]),
??????????? flash_socket_server_accpet(LSock);
??????? {error, Reason} ->
??????????? io:format("flash socket server exit: ~s~n", [Reason]),
??????????? exit(Reason)
??? end.
flash_socket_server_proc (Sock) ->
??? case gen_tcp:recv(Sock, 0) of
??????? {ok, Request} ->
??????????? io:format("Received: ~p~n", [Request]),
??????????? gen_tcp:send(Sock, "done!"),
??????????? flash_socket_server_proc(Sock);
??????? {error, closed} ->
??????????? io:format("Client closed~n"),
??????????? exit(closed);
??????? {error, Reason} ->
??????????? io:format("Error: ~s~n", Reason),
??????????? exit(Reason)
??? end.
在调试Flash端时,我调试了很久都没有效果,最后发现原来是浏览器缓存问题。
以下是Flash端的实验代码:
package
{
??? import flash.events.MouseEvent;
??? import flash.events.ProgressEvent;
??? import flash.net.Socket;
??? import flash.display.Sprite;
??? import flash.text.TextField;
??? import flash.text.TextFieldAutoSize;
??? public class Main extends Sprite
??? {
??????? private var sock:Socket;
??????? private var send:TextField;
??????? private var input:TextField;
??????? private var output:TextField;
??????? public function Main ()
??????? {
??????????? send = new TextField();
??????????? send.border = true;
??????????? send.multiline = true;
??????????? send.autoSize = TextFieldAutoSize.CENTER;
??????????? send.htmlText = "<a href='event:#'>?? Send?? </a>";
??????????? send.mouseEnabled = true;
??????????? send.selectable = false;
??????????? send.x = 320 - send.width;
??????????? send.y = 20;
??????????? send.height = 21;
??????????? input = new TextField();
??????????? input.border = true;
??????????? input.type = "input";
??????????? input.autoSize = TextFieldAutoSize.NONE;
??????????? input.x = 20;
??????????? input.y = 20;
??????????? input.width = 300 - send.width - 10;
??????????? input.height = 19;
??????????? output = new TextField();
??????????? output.border = true;
??????????? output.multiline = true;
??????????? output.autoSize = TextFieldAutoSize.NONE;
??????????? output.x = 20;
??????????? output.y = 20 + input.height + 10;
??????????? output.width = 300;
??????????? output.height = 300;
??????????? output.wordWrap = true;
??????????? addChild(send);
??????????? addChild(input);
??????????? addChild(output);
??????????? sock = new Socket();
??????????? sock.addEventListener(
??????????????? ProgressEvent.SOCKET_DATA,
??????????????? function (event:ProgressEvent):void
??????????????? {
??????????????????? /* 与Erlang端{packet, 0}对应的代码
??????????????? while (sock.bytesAvailable)
??????????????????? {
??????????????????????? var s:String = sock.readUTFBytes(sock.bytesAvailable);
??????????????????????? output.appendText(s);
??????????????????? }
??????????????????? */
??????????????????? /* 与Erlang端{packet, 0}对应的代码 */
??????????????????? var s:String = sock.readUTF();
??????????????????? input.text = "";
??????????????????? output.appendText(s);
??????????????????? output.appendText("\r\n");
??????????????? }
??????????? );
??????????? sock.connect("localhost", 10086);
??????????? sock.flush();
??????????? send.addEventListener(
??????????????? MouseEvent.CLICK,
??????????????? function (event:MouseEvent):void
??????????????? {
??????????????????? /* 与Erlang端{packet, 0}对应的代码
??????????????????? sock.writeUTFBytes("Hello World!");
??????????????????? */
??????????????????? /* 与Erlang端{packet, 0}对应的代码 */
??????????????????? sock.writeUTF(input.text);
??????????????????? sock.flush();
??????????????? }
??????????? );
??????? }
??? }
}