FlexでSokectを使うときのに応答する
FlexはSocketが使えるわけですが、サーバーとの接続開始時に(正確にはTCP3ウェイハンドシェイクが完了したあとFlashPlayerから)
<policy-file-request/>\0
という文字列を送ってきます。
このとき、Socket.connect()で指定したポートもしくは、Socket.connect()で指定したホストのポート843もしくは、Security.loadPolicyFile()で指定したポートに要求が飛びます。
これは、FlashPlayerがドメイン間での接続許可をサーバ側に求めています。
まとめて書くとわかりにくいので、例を。
パターン1) Socket.connect("hoge.com", 8888); //hoge.comのポート843問い合わせ、応答がない場合ポート8888に問い合わせます。 //このときポート843で応答があった場合、コネクションが成立し、8888に問い合わせません。 パターン2) Security.loadPolicyFile("xmlSocket://hoge.com:7777") Socket.connect("hoge.com", 8888); //hoge.comのポート7777に問い合わせ、応答がない場合はポート8888に問い合わせます。 //このときポート7777で応答があった場合、コネクションが成立し、8888に問い合わせません。
さらに接続先のポートが1024以上と以下で挙動が異なります。
パターン1) 接続先ポート1024以下から認証があった場合、すべてのポートに対してコネクションが張れます。 パターン2) 接続先ポート1024以上から認証があった場合、すべての1024番以上のポートに対してコネクションが張れます。
//これ以外にも一つのページに複数のSWFがあるときとか、一つのSWFから複数コネクションを張るなどいろいろテストしたいところ
これに対してサーバーは、
<cross-domain-policy><allow-access-from domain="*" to-ports="*"/></cross-domain-policy>\0
と応答してあげることで、接続してきたSWFとコネクションが張ることができます。
このとき、サーバ側は応答メッセージを返したあと、一度コネクションを切断します。
するとコネクション切断を検知したFlashPlayerが再度接続してくることで、サーバとの通信が開始されます。
(一度切断する理由はわかりませんが、FlashPlayerの仕様みたいです。)
これについて、Flexにはドメイン間ロード許可としてcrossdomain.xmlを用いるのが一般的ですが、SocketおよびXMLSocketを用いるときはcrossdomain.xmlの内容にかかわらずサーバーの応答のみをみて、接続するかしないかを決めています。
というわけで、クライアントから要求が着たら応答するものをPHPで書いてみた。
<?php echo "socket listen start\n"; //Listenするポート番号 $port = 8888; $sock = socket_create_listen($port); while(1) { $clientsock = socket_accept($sock); while(1) { /* * 接続確認 * クライアントから切断した時はclose */ if($buf = socket_read($clientsock, 1024)) { if(strlen($buf) > 0) { /* * Flex Connection start * Flexに応答を返していったん接続をきる。 */ if($buf == "<policy-file-request/>\0") { echo "flex comes\n"; //応答 $flex_auth = "<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0"; socket_write($clientsock, $flex_auth); socket_close($clientsock); $clientsock = socket_accept($sock); } socket_write($clientsock, $buf); } } else { break; } } socket_close($clientsock); echo "closed\n"; } socket_close($sock); ?>
これで一通りつながります。
あとはサーバからsocket_write()をすると、Flex側でDataEvent.DATAが発生するので、事前に
addEventListener(DataEvent.DATA, dataHandler);
とすることでデータを受け取ることができます。