Flashからconsole.logに出力できるのは便利だなー。
クライアント
echo_client.as
import flash.external.ExternalInterface; class EchoClient { static function main() { var log = function(msg) { ExternalInterface.call('window.console.log', msg); } var socket = new XMLSocket(); socket.onConnect = function (success) { log('onConnect(): ' + success); } socket.onData = function (src) { log('onData(): ' + src); ExternalInterface.call('recv_from_echod', src); } ExternalInterface.addCallback('connect_to_echod', null, function() { var connected = socket.connect(null, 10007); log('connect(): ' + connected); }); ExternalInterface.addCallback('close_from_echod', null, function() { socket.close(); log('close()'); }); ExternalInterface.addCallback('send_to_echod', null, function(msg) { socket.send(msg); }); }; }
MTASCでコンパイル。
~$ mtasc -version 8 -swf echo_client.swf -main echo_client.as -header 0:0:0
echo_client.html
<html> <head> <script type="text/javascript"> function $(id) { return document.getElementById(id); } function $M(movieName) { return (navigator.appName.indexOf("Microsoft") != -1) ? window[movieName] : document[movieName]; } function recv_from_echod(msg) { alert(msg); } </script> </head> <body> <object id="myflash" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="0" height="0"> <param NAME="movie" VALUE="echo_client.swf"> <embed name="myflash" src="echo_client.swf" width="0" height="0"></embed> </object> <input id="send_text" type="text"> <input type="button" value="send" onclick="$M('myflash').send_to_echod($('send_text').value);"> <br> <input type="button" value="connect" onclick="$M('myflash').connect_to_echod();"> <input type="button" value="close" onclick="$M('myflash').close_from_echod();"> </body> </html>
サーバ
require 'socket' class TCPSocket def recv_from_flush buf = '' while c = self.getc c.nonzero? or break buf << c end return buf end end alive = true trap(:INT) { alive = false } TCPServer.open('localhost', 10007) {|sock| while alive select([sock], nil, nil, 0.5) or next Thread.fork(sock.accept) {|s| puts 'accepted.' while msg = s.recv_from_flush not msg.empty? or break p msg if /policy-file-request/ =~ msg # s.write(<ポリシーのXML>)とか書いていたような… # コピペミスかな? break else s.write("#{msg}\0") end s.flush end s.close puts 'closed.' } end }
つまずいたとことか
- loadPolicyFile()を呼び出さないと、connectしたホスト・ポートからポリシーファイルの取得を試みる
- ポリシーファイルを送信するときには、末尾に\0は不要
- 普通のメッセージの終端は\0
- 「XMLSocket を 1024 以下のポートに接続するには、アプリケーションが独自の正確なドメインに接続している場合でも、最初に System.security.loadPolicyFile() メソッドを使用してポリシーファイルをロードする必要があります」とのこと