templates/as3/org/rubyforge/dango/DangoClientFramework.as in dango_generator-0.1.0 vs templates/as3/org/rubyforge/dango/DangoClientFramework.as in dango_generator-0.2.2
- old
+ new
@@ -1,428 +1,537 @@
package org.rubyforge.dango {
- /**
- * Dangoのクライアントフレームワーク本体のクラス
- *
- */
-
- import flash.net.*;
- import flash.events.*;
- import flash.text.*;
- import flash.utils.*;
- import flash.system.*;
- import mx.utils.ObjectUtil;
-
- import com.adobe.serialization.json.JSON;
-
- import flash.events.IEventDispatcher;
- import flash.events.EventDispatcher;
- import flash.events.Event;
+ /**
+ * Dangoのクライアントフレームワーク本体のクラス
+ *
+ */
+
+ import flash.net.*;
+ import flash.events.*;
+ import flash.text.*;
+ import flash.utils.*;
+ import flash.system.*;
+ import flash.display.*;
+ import mx.utils.ObjectUtil;
+
+ import com.adobe.serialization.json.JSON;
+
+ import flash.events.IEventDispatcher;
+ import flash.events.EventDispatcher;
+ import flash.events.Event;
- import org.rubyforge.dango.DangoUtil;
- import org.rubyforge.dango.DangoErrorCode;
+ import org.rubyforge.dango.DangoUtil;
+ import org.rubyforge.dango.DangoErrorCode;
- public class DangoClientFramework implements IEventDispatcher {
+ public class DangoClientFramework implements IEventDispatcher {
- private var socket:Socket; //ソケット
- private var dispatcher:EventDispatcher; // Event送出用
-
- private var is_debug:Boolean; // Debugモードかどうかのフラグ
- private var is_connect:Boolean = false; // 接続完了しているかどうか
-
- private var receve_count:uint = 0; // データ受信回数
-
- private var recv_not_yet_size:uint = 0; // データ受信時のキャッシュ
- private var recv_not_yet_str:String = ""; // データ受信時のキャッシュ
-
- private var polling_timer:Timer; // ポーリング(ハートビート)用タイマーの設定
- private var polling_timer_msec:uint = 5000; // ポーリング(ハートビート)用タイマーのミリ秒
-
- private var delay_send_timer:Timer; // 遅延送信用のタイマーの設定
- private var delay_send_timer_msec:uint = 1500; // 遅延送信用のタイマーのミリ秒
- private var delay_send_cache:Array = []; // 遅延送信用のキャッシュ
-
-// private var server_host:String = "172.31.1.74";
-// private var server_host:String = "localhost";
-// private var server_port:int = 15000;
- private var server_host:String;
- private var server_port:int;
-
- public var sid:int;
-
- /**
- * コンストラクタ
- *
- */
- public function DangoClientFramework(config:*, d:Boolean = false){
- is_debug = d; // Debugモードかどうかのフラグ
-
- // 設定ファイルの読み込み
- server_host = config.server_host;
- server_port = config.server_port;
-// is_debug = config.debug;
- is_debug = true;
-
- var policy_file_protocol:String = config.policy_file_protocol;
-// var policy_file_port:uint = config.policy_file_port;
- var policy_file_path:String = config.policy_file_path;
-
-
- // Event送出用
- dispatcher = new EventDispatcher(this);
-
- // Security.sandboxType
- trace("Security.sandboxType:" + Security.sandboxType);
-
- // policy_file
-// if(!policy_file_protocol){ policy_file_protocol = "http" };
- if(!policy_file_path) { policy_file_path = "/crossdomain.xml" };
-
- // ソケットの生成
- socket = new Socket();
-
- // ソケットのイベントリスナーの追加
- socket.addEventListener(Event.CONNECT, connectHandler, false);
- socket.addEventListener(Event.CONNECT, connectHandler, true);
- socket.addEventListener(Event.CLOSE, closeHandler, false);
- socket.addEventListener(Event.CLOSE, closeHandler, true);
- socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler, false);
- socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler, true);
- socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler, false);
- socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler, true);
- socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false);
- socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, true);
- trace("registered event handling.");
-
- // ポリシーファイルの読み込み
- if(policy_file_protocol){
- var url_load_policy_file:String;
-// url_load_policy_file = "xmlsocket://" + server_host + ":" + server_port;
-// url_load_policy_file = "http://aiarebaba.hi-fi-net.com/crossdomain.xml";
- url_load_policy_file = "http://" + server_host + policy_file_path;
- trace("url_load_policy_file=" + url_load_policy_file);
- Security.loadPolicyFile(url_load_policy_file);
- }
-
- // 接続
- try{
- trace("connectiong... host=" + server_host + " port=" + server_port);
- socket.connect(server_host, server_port);
- trace("connected host=" + server_host + " port=" + server_port);
- } catch(err:Error){
- trace("connect error err=" + err + " name=" + err.name + " message=" + err.message);
- return(void);
- }
-
- // polling用タイマーの設定
- var polling_timer:Timer = new Timer(polling_timer_msec, 0); // タイマーの追加
- polling_timer.addEventListener(TimerEvent.TIMER, polling_callback); // イベントリスナーの発行
- polling_timer.start(); // タイマーの作動開始
-
- // 遅延送信用タイマーの設定
- var delay_send_timer:Timer = new Timer(delay_send_timer_msec, 0); // タイマーの追加
- delay_send_timer.addEventListener(TimerEvent.TIMER, delay_send_callback); // イベントリスナーの発行
- delay_send_timer.start(); // タイマーの作動開始
- }
-
- //接続イベントの処理
- private function connectHandler(evt:Event):void {
- is_connect = true;
- var msg:String = "DangoClientFramework:connectHandler";
- if(is_debug){ trace(msg); }
- }
-
- //切断イベントの処理
- private function closeHandler(evt:Event):void {
- // タイマーが動いていれば止める
- if(polling_timer != null && polling_timer.running){ polling_timer.stop(); }
-
- is_connect = false;
- var msg:String = "DangoClientFramework:closeHandler";
- if(is_debug){ trace(msg); }
- this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.CloseError, msg));
- }
-
- //セキュリティエラーイベントの処理
- private function securityErrorHandler(evt:SecurityErrorEvent):void {
- // タイマーが動いていれば止める
- if(polling_timer != null && polling_timer.running){ polling_timer.stop(); }
-
- is_connect = false;
- var msg:String = "DangoClientFramework:securityErrorHandler:text=" + evt.text ;
-
- if(is_debug){ trace(msg); }
- this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.SecurityError, msg));
- }
-
- //IOエラーイベントの処理
- private function ioErrorHandler(evt:IOErrorEvent):void {
- // タイマーが動いていれば止める
- if(polling_timer != null && polling_timer.running){ polling_timer.stop(); }
-
- is_connect = false;
- var msg:String = "DangoClientFramework:ioErrorHandler";
- if(is_debug){ trace(msg); }
- this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.IOError, msg));
- }
-
- //プログレスイベントの処理(呼び出し用イベントのディスパッチ)
- private function socketDataHandler(evt:ProgressEvent):void {
- receve_count ++;
- if(is_debug){ trace("DangoClientFramework:socketDataHandler:" + receve_count); }
- var receive_data:Object = this.receive_notice();
-
- if(recv_not_yet_size == 0){ // 未受信データが無ければ
- if(receive_data != {}){ // データが空なら無視する
- var notice_name:String = receive_data["notice"];
-
- if(notice_name == "_notice_sid"){ // 接続直後のsid通知なら
- this.sid = receive_data["_sid"];
-// if(is_debug){ trace("DangoClientFramework:this.sid=" + this.sid + ":" + DangoUtil.now2str()); }
- if(is_debug){ trace("DangoClientFramework:this.sid=" + this.sid + ":" + receve_count); }
-
- } else if(notice_name == "_heart_beat"){ // heart beat通知なら
- if(is_debug){ trace("DangoClientFramework:_heart_beat:" + receve_count); }
-
- } else { // 通常のデータならイベント発生
- if(is_debug){ trace("DangoClientFramework:dispatchEvent:dango_" + notice_name + ":" + receve_count); }
- this.dispatchEvent(new DangoReceiveEvent("dango_" + notice_name, receive_data));
- }
- } else { // データが空なら
-// if(is_debug){ trace("DangoClientFramework:receive_data is empty." + DangoUtil.now2str()); }
- if(is_debug){ trace("DangoClientFramework:receive_data is empty."); }
- }
- }
- }
-
- // Event送出用
- public function addEventListener(type:String, listener:Function,
- useCapture:Boolean = false,
- priority:int = 0,
- useWeakReference:Boolean = false):void{
- dispatcher.addEventListener(type, listener, useCapture, priority);
- }
- public function dispatchEvent(evt:Event):Boolean{
- return dispatcher.dispatchEvent(evt);
- }
- public function hasEventListener(type:String):Boolean{
- return dispatcher.hasEventListener(type);
- }
- public function removeEventListener(type:String, listener:Function,
- useCapture:Boolean = false):void{
- dispatcher.removeEventListener(type, listener, useCapture);
- }
- public function willTrigger(type:String):Boolean {
- return dispatcher.willTrigger(type);
- }
-
-
- /**
- * polling_callback
- * ハートビートを送る
- *
- * @param evt:TimerEvent
- * @return void
- */
- public function polling_callback(evt:TimerEvent):void {
- if(is_debug){ trace("DangoClientFramework:polling_callback:" + DangoUtil.now2str() ); }
- if(socket.connected){
-// var send_obj:Object = null;
-// this.send_data_to_server(send_obj);
-
- var hb_id:String = String((new Date()).time) + String(this.sid);
- if(is_debug){ trace("DangoClientFramework:send _notice_heart_beat:" + hb_id + ":" + DangoUtil.now2str()); }
- this.send_action("_notice_heart_beat", { "_hb_id": hb_id}); // ハートビート送信
- }
- }
-
- /**
- * delay_send_callback
- * 遅延送信用タイマーコールバック
- *
- * @param socket:Socket
- * @param send_obj:Object
- * @return void
- */
- public function delay_send_callback(evt:TimerEvent):void {
-// if(is_debug){ trace("DangoClientFramework:delay_send_callback:evt:" + evt); }
- if(!is_connect){ return(void); }
- if(socket.connected){
- var send_obj_dup:Object;
- var i:uint;
-
- for (i = 0; i < 5; i++) {
- if(delay_send_cache.length == 0) { break; }
- send_obj_dup = delay_send_cache.pop();
- // データをすぐ送信
- this.send_data_to_server(send_obj_dup);
- if(is_debug){ trace("DangoClientFramework:delay_send_callback:sent:" + DangoUtil.now2str()); }
- }
- }
- }
-
- /**
- * send data to server.
- * クライアント側から使うサーバーへのデータ送信メソッド
- *
- * @param socket:Socket
- * @param send_obj:Object
- * @return void
- */
- public function send_action(action_name:String, send_obj:Object, delay:Boolean=false):void {
- if(is_debug){ trace("DangoClientFramework:send_action:start:" + action_name + ":" + DangoUtil.now2str()); }
-
-// if(!is_connect){ throw new DangoError("error:not connect" , 29); } // 接続されていない場合はエラー
-
- // 送信データの作成
- var send_obj_dup:Object = ObjectUtil.copy(send_obj);
- send_obj_dup["action"] = action_name;
-
- // delayフラグがあったり、接続がまだなら、遅延送信用のキャッシュにデータを入れる
- if(delay || !is_connect){
- delay_send_cache.push(send_obj_dup);
-
- if(is_debug){ trace("DangoClientFramework:send_action:delay_pull:" + action_name + ":" + DangoUtil.now2str()); }
- return(void);
- }
-
- // データをすぐ送信
- this.send_data_to_server(send_obj_dup);
- if(is_debug){ trace("DangoClientFramework:send_action:end:" + action_name + ":" + DangoUtil.now2str()); }
- }
-
- /**
- * send data to server.
- * フレームワーク側のデータ送信の一般処理
- *
- * @param socket:Socket
- * @param send_obj:Object
- * @return void
- */
- public function send_data_to_server( send_obj:Object ):void {
-// if(is_debug){ trace("DangoClientFramework:send_data_to_server:send_obj=" + ObjectUtil.toString(send_obj)); }
-
- var type:int = 0;
-
- // データが空ならJSONencodeしない
- var send_obj_str:String;
- if(send_obj == null){
- send_obj_str = "\n";
- } else {
- send_obj_str = JSON.encode(send_obj) + "\n";
- }
+ private var socket:Socket; //ソケット
+ private var dispatcher:EventDispatcher; // Event送出用
+
+ private var is_debug:Boolean; // Debugモードかどうかのフラグ
+ private var is_connect:Boolean = false; // 接続完了しているかどうか
+
+ private var receve_count:uint = 0; // データ受信回数
+ private var frame_rate:uint = 24; // デフォルトのフレームレート(想定値)
+ private var receive_cache:Array = []; // 受信データの一時保管用のキャッシュ
+
+ private var recv_not_yet_size:uint = 0; // データ受信時のキャッシュサイズ
+ private var recv_not_yet_str:String = ""; // データ受信時のキャッシュデータ
+
+ private var polling_timer:Timer; // ポーリング(ハートビート)用タイマーの設定
+ private var polling_timer_msec:uint = 5000; // ポーリング(ハートビート)用タイマーのミリ秒
+
+ private var delay_send_timer:Timer; // 遅延送信用のタイマーの設定
+ private var delay_send_timer_msec:uint = 1500; // 遅延送信用のタイマーのミリ秒
+ private var delay_send_cache:Array = []; // 遅延送信用のキャッシュ
+
+ private var recv_timer_msec:uint; // 受信用タイマーの実行間隔
+ private var recv_timer:Timer; // 受信用タイマーの追加
+ private var recv_last_date:Date = new Date(); // 受信用処理落ちチェック用
+
+// private var server_host:String = "172.31.1.74";
+// private var server_host:String = "localhost";
+// private var server_port:int = 15000;
+ private var server_host:String;
+ private var server_port:int;
+
+ public var sid:int;
+
+ /**
+ * コンストラクタ
+ *
+ */
+ public function DangoClientFramework(config:*, disp_obj:DisplayObject = null){
+// is_debug = d; // Debugモードかどうかのフラグ
+
+ if(disp_obj){
+ frame_rate = disp_obj.stage.frameRate; // フレームレート
+ }
+
+ // 設定ファイルの読み込み
+ server_host = config.server_host;
+ server_port = config.server_port;
+ is_debug = config.debug;
+// is_debug = true;
+
+ var policy_file_protocol:String = config.policy_file_protocol;
+// var policy_file_port:uint = config.policy_file_port;
+ var policy_file_path:String = config.policy_file_path;
+
+
+ // Event送出用
+ dispatcher = new EventDispatcher(this);
+
+ // Security.sandboxType
+ trace("Security.sandboxType:" + Security.sandboxType);
+
+ // policy_file
+// if(!policy_file_protocol){ policy_file_protocol = "http" };
+ if(!policy_file_path) { policy_file_path = "/crossdomain.xml" };
+
+ // ソケットの生成
+ socket = new Socket();
+
+ // ソケットのイベントリスナーの追加
+ socket.addEventListener(Event.CONNECT, connectHandler, false);
+ socket.addEventListener(Event.CONNECT, connectHandler, true);
+ socket.addEventListener(Event.CLOSE, closeHandler, false);
+ socket.addEventListener(Event.CLOSE, closeHandler, true);
+ socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler, false);
+ socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler, true);
+ socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler, false);
+ socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler, true);
+ socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false);
+ socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, true);
+ trace("registered event handling.");
+
+ // ポリシーファイルの読み込み
+ if(policy_file_protocol){
+ var url_load_policy_file:String;
+// url_load_policy_file = "xmlsocket://" + server_host + ":" + server_port;
+// url_load_policy_file = "http://aiarebaba.hi-fi-net.com/crossdomain.xml";
+ url_load_policy_file = "http://" + server_host + policy_file_path;
+ trace("url_load_policy_file=" + url_load_policy_file);
+ Security.loadPolicyFile(url_load_policy_file);
+ }
+
+ // 接続
+ try{
+ trace("connectiong... host=" + server_host + " port=" + server_port);
+ socket.connect(server_host, server_port);
+ trace("connected host=" + server_host + " port=" + server_port);
+ } catch(err:Error){
+ trace("connect error err=" + err + " name=" + err.name + " message=" + err.message);
+ return(void);
+ }
+
+ // polling用タイマーの設定
+ var polling_timer:Timer = new Timer(polling_timer_msec, 0); // タイマーの追加
+ polling_timer.addEventListener(TimerEvent.TIMER, polling_callback); // イベントリスナーの発行
+ polling_timer.start(); // タイマーの作動開始
+
+ // 遅延送信用タイマーの設定
+ var delay_send_timer:Timer = new Timer(delay_send_timer_msec, 0); // タイマーの追加
+ delay_send_timer.addEventListener(TimerEvent.TIMER, delay_send_callback); // イベントリスナーの発行
+ delay_send_timer.start(); // タイマーの作動開始
+
+ // fps用タイマーの設定(3フレームごとに動かすよう変更)
+ recv_timer_msec = uint((1000 * 3) / frame_rate);
+ if(is_debug){ trace("DangoClientFramework:recv_timer_msec:" + recv_timer_msec); }
+ recv_timer = new Timer(recv_timer_msec, 0); // タイマーの追加
+ recv_timer.addEventListener(TimerEvent.TIMER, recv_callback); // イベントリスナーの発行
+ recv_timer.start(); // タイマーの作動開始
+
+ // 接続完了のときに接続完了をサーバーに通知するためのハートビート送信
+ var hb_id:String = make_heartbeat();
+ this.send_action("_notice_heart_beat", { "_hb_id": hb_id}, true); // ハートビート送信
+ }
+
+ //接続イベントの処理
+ private function connectHandler(evt:Event):void {
+ is_connect = true;
+ var msg:String = "DangoClientFramework:connectHandler:" + DangoUtil.now2str();
+ if(is_debug){ trace(msg); }
+ }
+
+ //切断イベントの処理
+ private function closeHandler(evt:Event):void {
+ // タイマーが動いていれば止める
+ if(polling_timer != null && polling_timer.running){ polling_timer.stop(); }
+
+ is_connect = false;
+ var msg:String = "DangoClientFramework:closeHandler:" + DangoUtil.now2str();
+ if(is_debug){ trace(msg); }
+ this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.CloseError, msg));
+ }
+
+ //セキュリティエラーイベントの処理
+ private function securityErrorHandler(evt:SecurityErrorEvent):void {
+ // タイマーが動いていれば止める
+ if(polling_timer != null && polling_timer.running){ polling_timer.stop(); }
+
+ is_connect = false;
+ var msg:String = "DangoClientFramework:securityErrorHandler:text=" + evt.text + ":" + DangoUtil.now2str();
+
+ if(is_debug){ trace(msg); }
+ this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.SecurityError, msg));
+ }
+
+ //IOエラーイベントの処理
+ private function ioErrorHandler(evt:IOErrorEvent):void {
+ // タイマーが動いていれば止める
+ if(polling_timer != null && polling_timer.running){ polling_timer.stop(); }
+
+ is_connect = false;
+ var msg:String = "DangoClientFramework:ioErrorHandler:" + DangoUtil.now2str();
+ if(is_debug){ trace(msg); }
+ this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.IOError, msg));
+ }
+
+/*
+ //プログレスイベントの処理(呼び出し用イベントのディスパッチ)
+ private function socketDataHandler(evt:ProgressEvent):void {
+ receve_count ++;
+ if(is_debug){ trace("DangoClientFramework:socketDataHandler:" + receve_count); }
+ var receive_data:Object = this.receive_notice();
+
+ if(recv_not_yet_size == 0){ // 未受信データが無ければ
+ if(receive_data != {}){ // データが空なら無視する
+ var notice_name:String = receive_data["notice"];
+
+ if(notice_name == "_notice_sid"){ // 接続直後のsid通知なら
+ this.sid = receive_data["_sid"];
+// if(is_debug){ trace("DangoClientFramework:this.sid=" + this.sid + ":" + DangoUtil.now2str()); }
+ if(is_debug){ trace("DangoClientFramework:this.sid=" + this.sid + ":" + receve_count); }
+
+ } else if(notice_name == "_heart_beat"){ // heart beat通知なら
+ if(is_debug){ trace("DangoClientFramework:_heart_beat:" + receve_count); }
+
+ } else { // 通常のデータならイベント発生
+ if(is_debug){ trace("DangoClientFramework:dispatchEvent:dango_" + notice_name + ":" + receve_count); }
+ this.dispatchEvent(new DangoReceiveEvent("dango_" + notice_name, receive_data));
+ }
+ } else { // データが空なら
+// if(is_debug){ trace("DangoClientFramework:receive_data is empty." + DangoUtil.now2str()); }
+ if(is_debug){ trace("DangoClientFramework:receive_data is empty."); }
+ }
+ }
+ }
+*/
+
+ // プログレスイベントの処理(呼び出し用イベントのディスパッチ)
+ // とにかくキャッシュに入れるだけ
+ private function socketDataHandler(evt:ProgressEvent):void {
+ receve_count ++;
+ if(is_debug){ trace("DangoClientFramework:socketDataHandler:" + receve_count + ":start:" + DangoUtil.now2str()); }
+ var byte_array:ByteArray = new ByteArray;
+ socket.readBytes(byte_array, 0, socket.bytesAvailable);
+ receive_cache.push([byte_array, receve_count]);
+ }
- var send_obj_size:int = DangoUtil.string_byte_length(send_obj_str);
-
-// if(is_debug){ trace("DangoClientFramework:send:" + type + ":" + send_obj_size + ":" + send_obj_str); }
+ // Event送出用
+ public function addEventListener(type:String, listener:Function,
+ useCapture:Boolean = false,
+ priority:int = 0,
+ useWeakReference:Boolean = false):void{
+ dispatcher.addEventListener(type, listener, useCapture, priority);
+ }
+ public function dispatchEvent(evt:Event):Boolean{
+ return dispatcher.dispatchEvent(evt);
+ }
+ public function hasEventListener(type:String):Boolean{
+ return dispatcher.hasEventListener(type);
+ }
+ public function removeEventListener(type:String, listener:Function,
+ useCapture:Boolean = false):void{
+ dispatcher.removeEventListener(type, listener, useCapture);
+ }
+ public function willTrigger(type:String):Boolean {
+ return dispatcher.willTrigger(type);
+ }
+
+
+ /**
+ * recv_callback
+ * フレームレート単位で動く処理(キャッシュにデータがあればデータ受信)
+ *
+ * @param evt:TimerEvent
+ * @return void
+ */
+ public function recv_callback(evt:TimerEvent):void {
+ if(is_debug){ trace("DangoClientFramework:recv_callback:" + DangoUtil.now2str()); }
+
+ // 前回から時間がかかりすぎている(処理落ち仕掛けている場合は)スキップ
+ var start_date:Date = new Date();
+ if(is_debug){ trace("DangoClientFramework:recv_last_date.time=" + recv_last_date.time + " start_date.time=" + start_date.time); }
+ if(recv_last_date.time > start_date.time - (recv_timer_msec * 1.5)){
+ if(receive_cache.length > 0){
+// while(receive_cache.length > 0){
+ if(is_debug){ trace("DangoClientFramework:recv_callback:receive_cache.length=" + receive_cache.length + ":" + DangoUtil.now2str()); }
+ var arr:Array = receive_cache.shift(); // Queueとして取り出し
+ var byte_array:ByteArray = arr[0];
+ var recv_c:uint = arr[1];
+ if(is_debug){ trace("DangoClientFramework:recv_c=" + recv_c); }
+ var receive_data:Array = this.receive_notice(byte_array);
+
+ if(recv_not_yet_size == 0){ // 未受信データが無ければ
+ if(receive_data != []){ // データが空なら無視する
+ for(var i:uint = 0; i < receive_data.length; i++){
+ var notice_name:String = receive_data[i]["notice"];
+
+ if(notice_name == "_notice_sid"){ // 接続直後のsid通知なら
+ this.sid = receive_data[i]["_sid"];
+ if(is_debug){ trace("DangoClientFramework:this.sid=" + this.sid + " recv_c:" + recv_c); }
+
+ } else if(notice_name == "_heart_beat"){ // heart beat通知なら
+ if(is_debug){ trace("DangoClientFramework:_heart_beat: recv_c:" + recv_c); }
+
+ } else { // 通常のデータならイベント発生
+ if(is_debug){ trace("DangoClientFramework:dispatchEvent:dango_" + notice_name + ": recv_c:" + recv_c + ":" + i); }
+ this.dispatchEvent(new DangoReceiveEvent("dango_" + notice_name, receive_data[i]));
+ }
+ }
+ } else { // データが空なら
+ // if(is_debug){ trace("DangoClientFramework:receive_data is empty." + DangoUtil.now2str()); }
+ if(is_debug){ trace("DangoClientFramework:receive_data is empty."); }
+ }
+ }
+
+/*
+ // 処理に時間がかかりすぎている場合は、スキップさせる(while用)
+ if(is_debug){ trace("DangoClientFramework:recv_callback:end_date:" + DangoUtil.now2str()); }
+ var end_date:Date = new Date();
+ if(start_date.time < end_date.time - recv_timer_msec){
+ if(is_debug){ trace("DangoClientFramework:break"); }
+ break;
+ }
+*/
+ }
+ }
+
+ recv_last_date = new Date();
+ }
+
+ /**
+ * polling_callback
+ * ハートビート用タイマーコールバック
+ *
+ * @param evt:TimerEvent
+ * @return void
+ */
+ public function polling_callback(evt:TimerEvent):void {
+ if(is_debug){ trace("DangoClientFramework:polling_callback:" + DangoUtil.now2str() ); }
+ if(socket.connected){
+// var send_obj:Object = null;
+// this.send_data_to_server(send_obj);
+
+ var hb_id:String = make_heartbeat();
+// if(is_debug){ trace("DangoClientFramework:send _notice_heart_beat:" + hb_id + ":" + DangoUtil.now2str()); }
+ this.send_action("_notice_heart_beat", { "_hb_id": hb_id}); // ハートビート送信
+ }
+ }
+
+ /**
+ * polling_callback
+ * ハートビートの作成
+ *
+ * @return String
+ */
+ public function make_heartbeat():String {
+ return(String((new Date()).time) + String(this.sid));
+ }
+
+ /**
+ * delay_send_callback
+ * 遅延送信用タイマーコールバック
+ *
+ * @param socket:Socket
+ * @param send_obj:Object
+ * @return void
+ */
+ public function delay_send_callback(evt:TimerEvent):void {
+// if(is_debug){ trace("DangoClientFramework:delay_send_callback:evt:" + evt); }
+ if(!is_connect){ return(void); }
+ if(socket.connected){
+ var send_obj_dup:Array;
+ var i:uint;
+
+ for (i = 0; i < 5; i++) {
+ if(delay_send_cache.length == 0) { break; }
+ send_obj_dup = delay_send_cache.pop();
+ // データをすぐ送信
+ this.send_data_to_server(send_obj_dup);
+ if(is_debug){ trace("DangoClientFramework:delay_send_callback:sent:" + DangoUtil.now2str()); }
+ }
+ }
+ }
+
+ /**
+ * send data to server.
+ * クライアント側から使うサーバーへのデータ送信メソッド
+ *
+ * @param socket:Socket
+ * @param send_obj:Object
+ * @return void
+ */
+ public function send_action(action_name:String, send_obj:Object, delay:Boolean=false):void {
+ if(is_debug){ trace("DangoClientFramework:send_action:start:" + action_name + ":" + DangoUtil.now2str()); }
+
+// if(!is_connect){ throw new DangoError("error:not connect" , 29); } // 接続されていない場合はエラー
+
+ // 送信データの作成
+ var send_obj_dup:Object = ObjectUtil.copy(send_obj);
+ send_obj_dup["action"] = action_name;
+ send_obj_dup["_return_id"] = (new Date()).time;
+
+ // delayフラグがあったり、接続がまだなら、遅延送信用のキャッシュにデータを入れる
+ if(delay || !is_connect){
+ delay_send_cache.push([send_obj_dup]);
+
+ if(is_debug){ trace("DangoClientFramework:send_action:delay_pull:" + action_name + ":" + DangoUtil.now2str()); }
+ return(void);
+ }
+
+ // データをすぐ送信
+ this.send_data_to_server([send_obj_dup]);
+ if(is_debug){ trace("DangoClientFramework:send_action:end:" + action_name + ":" + DangoUtil.now2str()); }
+ }
+
+ /**
+ * send data to server.
+ * フレームワーク側のデータ送信の一般処理
+ *
+ * @param socket:Socket
+ * @param send_obj:Object
+ * @return void
+ */
+ public function send_data_to_server( send_obj:Array ):void {
+// if(is_debug){ trace("DangoClientFramework:send_data_to_server:send_obj=" + ObjectUtil.toString(send_obj)); }
+
+ var type:int = 0;
+
+ // データが空ならJSONencodeしない
+ var send_obj_str:String;
+ if(send_obj == null){
+ send_obj_str = "\n";
+ } else {
+ send_obj_str = JSON.encode(send_obj) + "\n";
+ }
- // 長さ送信
- var byte_array:ByteArray = new ByteArray;
- byte_array.writeByte(type);
- byte_array.writeUnsignedInt(send_obj_size);
+ var send_obj_size:int = DangoUtil.string_byte_length(send_obj_str);
+
+// if(is_debug){ trace("DangoClientFramework:send:" + type + ":" + send_obj_size + ":" + send_obj_str); }
- socket.writeBytes(byte_array, 0, 5);
- socket.writeUTFBytes("\n");
- socket.flush();
+ // 長さ送信
+ var byte_array:ByteArray = new ByteArray;
+ byte_array.writeByte(type);
+ byte_array.writeUnsignedInt(send_obj_size);
- // データ送信
- socket.writeUTFBytes(send_obj_str);
- socket.flush();
-
-// if(is_debug){ trace("DangoClientFramework:send_obj_str:" + send_obj_str + ":" + DangoUtil.now2str()); }
- }
-
- /**
- * receive data from server.
- * フレームワーク側のデータ受信の一般処理
- *
- * @return Object
- */
- public function receive_notice():Object {
- if(is_debug){ trace("DangoClientFramework:receive_notice:" + receve_count + ":" + DangoUtil.now2str()); }
+ socket.writeBytes(byte_array, 0, 5);
+ socket.writeUTFBytes("\n");
+ socket.flush();
- // 変数定義
- var recv_data_orig:String = "";
- var bytes_available:uint;
-
- // まず読めるデータをすべてByteArrayに入れる
- var byte_array:ByteArray = new ByteArray;
- socket.readBytes(byte_array, 0, socket.bytesAvailable);
- var byte_read_size:uint = byte_array.length;
-
- if(recv_not_yet_size == 0){ // 未受信データが無ければ
-// if(is_debug){ trace("DangoClientFramework:recv_not_yet_size==0"); }
-
- if(byte_read_size < 6){ // きちんとデータが届いていなければ
- this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.IOError, "byte_read_size is too short."));
- return({});
- }
-
- // 長さを取得
- var byte_array_size:ByteArray = new ByteArray;
- try{
- byte_array.readBytes(byte_array_size, 0, 5);
- } catch(err:Error){
- this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.IOError, "failed to byte_array.readBytes."));
- return({});
- }
-
- var type:int = byte_array_size.readByte();
- recv_not_yet_size = byte_array_size.readUnsignedInt();
- var crlf:String = byte_array.readUTFBytes(1);
- byte_read_size -= 6;
-// if(is_debug){ trace("DangoClientFramework:recv_not_yet_size=" + recv_not_yet_size); }
- }
-
- // 読めているだけ読んで、その分recv_not_yet_sizeを減らす
- if(recv_not_yet_size > byte_read_size){
-// if(is_debug){ trace("DangoClientFramework:byte_read_size=" + byte_read_size); }
- recv_data_orig = byte_array.readUTFBytes(byte_read_size);
- recv_not_yet_size -= byte_read_size;
- }else{
-// if(is_debug){ trace("DangoClientFramework:recv_not_yet_size=" + recv_not_yet_size); }
- recv_data_orig = byte_array.readUTFBytes(recv_not_yet_size);
- recv_not_yet_size = 0;
- }
-
-// if(is_debug){ trace("DangoClientFramework:recv_data_orig:" + recv_data_orig); }
-
- // 全データを受信したかどうかを確認
- if(recv_not_yet_size == 0){ // 受信完了ならJSONパース
- var recv_data:String = recv_not_yet_str + recv_data_orig;
- recv_not_yet_str = "";
-
-// if(is_debug){ trace("DangoClientFramework:recieve:data=" + ObjectUtil.toString(recv_data)); }
-
- var ret_obj_data:Object;
- if(recv_data && recv_data != "" && recv_data != "\n"){ // データが空じゃないならdecode
- ret_obj_data = JSON.decode(recv_data) as Object;
-
- } else { // データが空なら空データを作ってreturn
- ret_obj_data = {};
- return(ret_obj_data);
- }
-
- // ret_obj_dataがObjectでnoticeが存在しているかのチェック
- if(!(ret_obj_data is Object) || !(ret_obj_data["notice"] is String)){
- if(!is_connect){ throw new DangoError("error:recieve data is invalid." , 29); }
- }
-
- if(ret_obj_data["notice"] == "_notice_sid"){
- if(is_debug){ trace("DangoClientFramework:recieve:_notice_sid:no response:" + receve_count + ":" + DangoUtil.now2str()); }
- }else{
- var response_notice_name:String;
- response_notice_name = "_response";
- if(is_debug){ trace("DangoClientFramework:sending:response:notice_name=" + ret_obj_data["notice"] + ":" + ret_obj_data["_id"] + ":" + receve_count + ":" + DangoUtil.now2str()); }
-
- this.send_action(response_notice_name, {"_id":ret_obj_data["_id"]}); // 受信完了確認の為に空データを送る
- }
- return(ret_obj_data);
-
- } else { // まだデータが残っているなら空を返す
- recv_not_yet_str += recv_data_orig;
- return({});
- }
- }
-
- }
+ // データ送信
+ socket.writeUTFBytes(send_obj_str);
+ socket.flush();
+
+// if(is_debug){ trace("DangoClientFramework:send_obj_str:" + send_obj_str + ":" + DangoUtil.now2str()); }
+ }
+
+ /**
+ * receive data from server.
+ * フレームワーク側のデータ受信の一般処理
+ *
+ * @return Object
+ */
+ public function receive_notice(byte_array:ByteArray):Array {
+ if(is_debug){ trace("DangoClientFramework:receive_notice:" + DangoUtil.now2str()); }
+
+ // 変数定義
+ var recv_data_orig:String = "";
+
+ // まず読めるデータをすべてByteArrayに入れる
+// var byte_array:ByteArray = new ByteArray;
+// socket.readBytes(byte_array, 0, socket.bytesAvailable);
+
+ // 読んだデータの長さ取得
+ var byte_read_size:uint = byte_array.length;
+
+ if(recv_not_yet_size == 0){ // 未受信データが無ければ
+// if(is_debug){ trace("DangoClientFramework:recv_not_yet_size==0"); }
+
+ if(byte_read_size < 6){ // きちんとデータが届いていなければ
+ this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.IOError, "byte_read_size is too short."));
+ return([]);
+ }
+
+ // 長さを取得
+ var byte_array_size:ByteArray = new ByteArray;
+ try{
+ byte_array.readBytes(byte_array_size, 0, 5);
+ } catch(err:Error){
+ this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.IOError, "failed to byte_array.readBytes."));
+ return([]);
+ }
+
+ var type:int = byte_array_size.readByte();
+ recv_not_yet_size = byte_array_size.readUnsignedInt();
+ var crlf:String = byte_array.readUTFBytes(1);
+ byte_read_size -= 6;
+// if(is_debug){ trace("DangoClientFramework:recv_not_yet_size=" + recv_not_yet_size); }
+ }
+
+ // 読めているだけ読んで、その分recv_not_yet_sizeを減らす
+ if(recv_not_yet_size > byte_read_size){
+// if(is_debug){ trace("DangoClientFramework:byte_read_size=" + byte_read_size); }
+ recv_data_orig = byte_array.readUTFBytes(byte_read_size);
+ recv_not_yet_size -= byte_read_size;
+ }else{
+// if(is_debug){ trace("DangoClientFramework:recv_not_yet_size=" + recv_not_yet_size); }
+ recv_data_orig = byte_array.readUTFBytes(recv_not_yet_size);
+ recv_not_yet_size = 0;
+ }
+
+// if(is_debug){ trace("DangoClientFramework:recv_data_orig:" + recv_data_orig); }
+
+ // 全データを受信したかどうかを確認
+ if(recv_not_yet_size == 0){ // 受信完了ならJSONパース
+ var recv_data:String = recv_not_yet_str + recv_data_orig;
+ recv_not_yet_str = "";
+
+// if(is_debug){ trace("DangoClientFramework:recieve:data=" + ObjectUtil.toString(recv_data)); }
+
+ var ret_obj_data:Array;
+ if(recv_data && recv_data != "" && recv_data != "\n"){ // データが空じゃないならdecode
+ ret_obj_data = JSON.decode(recv_data) as Array;
+
+ } else { // データが空なら空データを作ってreturn
+ return([]);
+ }
+
+ // ret_obj_dataがObjectでnoticeが存在しているかのチェック
+ if(!(ret_obj_data is Array) || !(ret_obj_data[0]["notice"] is String)){
+// if(!is_connect){ throw new DangoError("error:recieve data is invalid." , 29); }
+ throw new DangoError("error:recieve data is invalid." , 29);
+ }
+
+/*
+ if(ret_obj_data["notice"] == "_notice_sid"){
+ if(is_debug){ trace("DangoClientFramework:recieve:_notice_sid:no response:" + receve_count + ":" + DangoUtil.now2str()); }
+ }else{
+ var response_notice_name:String;
+ response_notice_name = "_response";
+ if(is_debug){ trace("DangoClientFramework:sending:response:notice_name=" + ret_obj_data["notice"] + ":" + ret_obj_data["_id"] + ":" + receve_count + ":" + DangoUtil.now2str()); }
+
+ this.send_action(response_notice_name, {"_id":ret_obj_data["_id"]}); // 受信完了確認の為に空データを送る
+ }
+*/
+ return(ret_obj_data);
+
+ } else { // まだデータが残っているなら空を返す
+ recv_not_yet_str += recv_data_orig;
+ return([]);
+ }
+ }
+
+ }
}