アクセシビリティ
デベロッパーリソース

目次

Flex + LL連携(Ruby、Python、PHP)

サーバと通信してみる

Flex/Flashがサーバ側と通信する方法は、幾つかあります。
一番原始的な方法は、Webサーバに対し、GET/POSTメソッドを用いて、データを送受信することです。
これは、普通のHTMLのフォームで「送信」ボタンを押したときに行われるのと同じ処理を、Flex/Flashでも行うやり方です。
flash.netパッケージのAPIであるURLLoaderクラス、URLRequestクラスを使います。
簡単なサンプルを見てみましょう。

Flexで、ホームページで利用するための単純なゲストブックを作るとしましょう。
入力出来るのは、名前とEメールアドレス、感想の3項目です。
まずはFlex側のUIを作ります。項目も少ないし、簡単ですね。
「送信」ボタンが押されたら、入力されたデータをサーバに送信するようにしてみましょう。
その際、入力された名前を「name」、Eメールアドレスは「email」、感想は「comment」として送信します。
URLRequestが、要求を表現するクラスです。要求を送信する宛先URLや渡すパラメータを設定します。
URLLoaderが実際の要求を実行するクラスです。要求が成功した時のハンドラ、失敗した時のハンドラなどを登録しましょう。
URLLoaderは、デフォルトではGETメソッドを使って要求を送信しますが、今回はPOSTメソッドを明示的に指定します。

画面のイメージ
SCREEN

Guestbook.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="srcview/index.html">
         <mx:Script><![CDATA[
                   private function buttonClickHandler(e:Event):void
                   {
                            // サーバ側の処理スクリプトのURL
                            const kDestUrl:String = "http://localhost/guestbook/guestbook.php";
 
                            var request:URLRequest = new URLRequest(kDestUrl);
                            request.method = URLRequestMethod.POST;
                            var vars:URLVariables = new URLVariables();
                            vars.name = tiName.text;
                            vars.email = tiEmail.text;
                            vars.comment = tiComment.text;
                            request.data = vars;
                            lblServerResult.text = "";
                            var loader:URLLoader = new URLLoader();
                            try {
                                     loader.load(request);
                            }
                            catch (error:SecurityError){
                                     trace("リクエスト時にセキュリティエラーが発生しました.");
                            }
                            loader.addEventListener(IOErrorEvent.IO_ERROR, onIOError, false, 0, true);
                            loader.addEventListener(Event.COMPLETE, onLoadComplete, false, 0, true);
                   }
 
                   private function onIOError(event:IOErrorEvent):void
                   {
                            trace("IOエラー");
                   }
 
                   private function onSecurityError(event:SecurityErrorEvent):void
                   {
                            trace("セキュリティエラー");
                   }
 
                   private function onLoadComplete(e:Event):void
                   {
                            var result:String = URLLoader(e.target).data as String; 
                            if (result)
                            {
                                     lblServerResult.text = result;
                                     trace("サーバからのデータのロードに成功しました。受信データ: " + result);
                            }
                   }
         ]]></mx:Script>
 
         <mx:Form width="100%">
                   <mx:FormItem label="お名前">
                            <mx:TextInput id="tiName" />
                   </mx:FormItem>
                   
                   <mx:FormItem label="Eメールアドレス">
                            <mx:TextInput id="tiEmail" />
                   </mx:FormItem>
         
                   <mx:FormItem label="ひとこと">
                            <mx:TextArea id="tiComment"/>
                   </mx:FormItem>
         </mx:Form>
 
         <mx:HBox width="100%">
                   <mx:Button label="送信" left="0" click="buttonClickHandler(event)" />
 
                   <mx:Label text="サーバからの応答:"/> <mx:Label id="lblServerResult" />
         </mx:HBox>
</mx:Application>

サーバサイドのスクリプトは以下のようになります。PHPで記述しました。
サーバサイドでは、送られてきたパラメータを受け取った後、必要な処理を行います。
標準出力に書き出した内容が、結果としてクライアントサイドに渡されます。

<?php
if (isset($_POST["name"]) && isset($_POST["email"]) && isset($_POST["comment"]))
{
  $name = $_POST["name"];
  $email = $_POST["email"];
  $comment = $_POST["comment"];
  print "name=$name/email=$email/comment=$comment";
}
else 
{
  print "error";
}

もっと良い方法

HTTPのGET/POSTメソッドでデータをやり取りする例を見てきました。
簡単な処理ですが、それなりの手間は掛かりますね。
実はFlex・Flashでは、サーバサイドと通信するのに、もっと良い方法があります。
それは、サーバサイドで"RPCサービス"を作成して、Flex・Flashから、そのサービスのメソッドを呼ぶやり方です。

「RPC」とは”Remote Procedure Call”の略で、名前の通り、遠隔にあるプロシージャ(=メソッド)を呼び出しを可能にする技術のことを指します。
要は、サーバサイドでサービスを書いて登録すると、クライアントは、ローカルのメソッドを呼ぶのと同じように、サーバサイドのサービスのメソッドを呼ぶことができます。

RPCで何が嬉しいかというと、まず直感的に使えることがあります。ローカルのメソッドを呼ぶような感覚で、サーバサイドのメソッドが呼べるのは便利です。
しかし、更に重要なのは効率です。
最初に紹介したGET/POSTを使う方法や、XML/JSONといったテキスト表現でデータを送受信する方法では、サーバ・クライアント間で流れるデータは全てが文字列になってしまいます。これは効率が良くありません。
例えば、int型を受け渡すことを考えてみましょう。クライアントサイドからint型の値を送る際、一旦文字列型に変換されます。
int -> 文字列 -> 文字列 -> 文字列 ->int
(クライアント) (サーバ) (クライアント)
という流れになりますが、文字列型とint型との相互変換が発生するのが無駄です。
Flex・FlashのRPC呼び出しで使われるAMFフォーマットは、バイナリ形式のため冗長性が低く、そもそも効率的なデータのやりとりが可能ということもありますが、それだけではなく、Flash Playerがネイティブに扱えるフォーマットというのが重要なポイントです。

前述の例で言えば、RPC呼び出し時には
int -> int ->int
(クライアント) (サーバ) (クライアント)
となり、余計な中間オブジェクトが生成されません。クライアントサイドではint型はActionScriptの型からAMFに直接シリアライズされますし、サーバサイドでもAMFからサーバサイドの言語の対応する型にデシリアライズされます。
上記の例では軽微な差で、重要性があまり感じられないかもしれませんが、非常に頻繁にデータをやりとりするシステムではこの差が大きく影響してきます。例えば、株価情報を毎秒チェックし続けるクライアントを考えてみてください。
他にも、高解像度画像など非常に大きなデータを扱うシステムでも、この差が全体のパフォーマンスに大きな影響を与えることでしょう。もしサーバから送られてきた画像がBase64エンコードの文字列なら、文字列を画像に変換するのに多くのメモリを使用しなければなりません。サーバサイドで画像を適切な型(ByteArray)にエンコードしさえすれば、変換の際に必要になるメモリはそもそも不要です。