templates/as3/org/rubyforge/dango/DangoClientFramework.as in dango_generator-0.3.4 vs templates/as3/org/rubyforge/dango/DangoClientFramework.as in dango_generator-0.3.5
- old
+ new
@@ -1,6 +1,6 @@
-
+
package org.rubyforge.dango {
/**
* Dangoのクライアントフレームワーク本体のクラス
*
*/
@@ -39,19 +39,16 @@
private var delay_send_timer:Timer; // 遅延送信用のタイマーの設定
private var delay_send_timer_msec:uint = 1500; // 遅延送信用のタイマーのミリ秒
private var delay_send_cache:Array = []; // 遅延送信用のキャッシュ
- private var receve_count:uint = 0; // データ受信回数
- private var receive_row_cache:Array = []; // 受信データの一時保管用のキャッシュ
+ private var receive_cache_byta:ByteArray = new ByteArray; // 受信データの保管用のキャッシュ ByteArray
+ private var receive_cache_do_phase:uint = 0; // 受信データをどこまで処理してあるかのキャッシュ
+ private var receive_encode_type:uint = 0; // 受信データのエンコードタイプ
+ private var receive_data_size:uint = 0; // 受信データのデータサイズ
- private var recv_not_yet_size:uint = 0; // データ受信時のキャッシュサイズ
- private var recv_not_yet_str:String = ""; // データ受信時のキャッシュデータ
-
private var recv_wait_do_cache:Array = []; // 実行待ち受信キャッシュ
- private var recv_cache_timer_msec:uint; // 受信キャッシュ用タイマーの実行間隔
- private var recv_cache_timer:Timer; // 受信キャッシュ用タイマーの追加
private var recv_do_count_no:uint = 0; // 受信実行の回数
private var recv_do_timer_msec:uint; // 受信実行用タイマーの実行間隔
private var recv_do_timer:Timer; // 受信実行用タイマーの追加
private var recv_do_last_date:Date = new Date(); // 受信キャッシュ用処理落ちチェック用
@@ -65,12 +62,16 @@
private var server_port:int;
public var sid:int;
/**
+ * DangoClientFramework
* コンストラクタ
*
+ * @param config:*
+ * @param disp_obj:DisplayObject = null
+ * @return void
*/
public function DangoClientFramework(config:*, disp_obj:DisplayObject = null){
// is_debug = d; // Debugモードかどうかのフラグ
if(disp_obj){
@@ -147,17 +148,10 @@
// 遅延送信用タイマーの設定
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(); // タイマーの作動開始
- // 受信キャッシュ用タイマーの設定(4フレームごとに動かすよう変更)
- recv_cache_timer_msec = uint((1000 * 4) / frame_rate);
- if(is_debug){ trace("DangoClientFramework:recv_cache_timer_msec:" + recv_cache_timer_msec); }
- recv_cache_timer = new Timer(recv_cache_timer_msec, 0); // タイマーの追加
- recv_cache_timer.addEventListener(TimerEvent.TIMER, recv_cache_callback); // イベントリスナーの発行
- recv_cache_timer.start(); // タイマーの作動開始
-
// 受信実行用タイマーの設定(2フレームごとに動かすよう変更)
recv_do_timer_msec = uint((1000 * 2) / frame_rate);
if(is_debug){ trace("DangoClientFramework:recv_do_timer_msec:" + recv_do_timer_msec); }
recv_do_timer = new Timer(recv_do_timer_msec, 0); // タイマーの追加
recv_do_timer.addEventListener(TimerEvent.TIMER, recv_do_callback); // イベントリスナーの発行
@@ -166,29 +160,47 @@
// 接続完了のときに接続完了をサーバーに通知するためのハートビート送信
var hb_id:String = make_heartbeat();
this.send_action("_notice_heart_beat", { "_hb_id": hb_id}, true); // ハートビート送信
}
- //接続イベントの処理
+ /**
+ * connectHandler
+ * 接続イベントの処理
+ *
+ * @param evt:Event
+ * @return void
+ */
private function connectHandler(evt:Event):void {
is_connect = true;
var msg:String = "DangoClientFramework:connectHandler:" + DangoUtil.now2str();
if(is_debug){ trace(msg); }
}
- //切断イベントの処理
+ /**
+ * closeHandler
+ * 切断イベントの処理
+ *
+ * @param evt:Event
+ * @return void
+ */
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));
}
- //セキュリティエラーイベントの処理
+ /**
+ * securityErrorHandler
+ * セキュリティエラーイベントの処理
+ *
+ * @param evt:Event
+ * @return void
+ */
private function securityErrorHandler(evt:SecurityErrorEvent):void {
// タイマーが動いていれば止める
if(polling_timer != null && polling_timer.running){ polling_timer.stop(); }
is_connect = false;
@@ -196,88 +208,203 @@
if(is_debug){ trace(msg); }
this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.SecurityError, msg));
}
- //IOエラーイベントの処理
+ /**
+ * ioErrorHandler
+ * IOエラーイベントの処理
+ *
+ * @param evt:Event
+ * @return void
+ */
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));
}
- // プログレスイベントの処理(呼び出し用イベントのディスパッチ)
- // とにかくキャッシュに入れるだけ
+ /**
+ * socketDataHandler
+ * プログレスイベントの処理:実体はsocket_read_push_cache
+ *
+ * @param evt:Event
+ * @return void
+ */
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_row_cache.push([byte_array, receve_count]);
+ socket_read_push_cache();
}
- // Event送出用
+ /**
+ * addEventListener
+ * Event送出用
+ *
+ * @param type:String
+ * @param listener:Function
+ * @param useCapture:Boolean = false
+ * @param priority:int = 0
+ * @param useWeakReference:Boolean = false
+ * @return void
+ */
public function addEventListener(type:String, listener:Function,
useCapture:Boolean = false,
priority:int = 0,
useWeakReference:Boolean = false):void{
dispatcher.addEventListener(type, listener, useCapture, priority);
}
+
+ /**
+ * dispatchEvent
+ * Event送出用
+ *
+ * @param evt:Event
+ * @return Boolean
+ */
public function dispatchEvent(evt:Event):Boolean{
return dispatcher.dispatchEvent(evt);
}
+
+ /**
+ * hasEventListener
+ * Event送出用
+ *
+ * @param type:String
+ * @return Boolean
+ */
public function hasEventListener(type:String):Boolean{
return dispatcher.hasEventListener(type);
}
+
+ /**
+ * removeEventListener
+ * Event送出用
+ *
+ * @param type:String
+ * @param listener:Function
+ * @param useCapture:Boolean = false
+ * @return void
+ */
public function removeEventListener(type:String, listener:Function,
useCapture:Boolean = false):void{
dispatcher.removeEventListener(type, listener, useCapture);
}
+
+ /**
+ * willTrigger
+ * Event送出用
+ *
+ * @param type:String
+ * @return Boolean
+ */
public function willTrigger(type:String):Boolean {
return dispatcher.willTrigger(type);
}
-
/**
- * recv_cache_callback
- * 受信データの再構成とキャッシュをする
+ * socket_read_push_cache
+ * socketDataHandlerの実体処理
+ * データ受信、データのパース、実行待ちキャッシュに保存
*
- * @param evt:TimerEvent
+ * @param void
* @return void
*/
- public function recv_cache_callback(evt:TimerEvent):void {
-// if(is_debug){ trace("DangoClientFramework:recv_cache_callback:" + DangoUtil.now2str()); }
+ private function socket_read_push_cache():void{
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:" + DangoUtil.now2str()); }
- if(receive_row_cache.length > 0){
- if(is_debug){ trace("DangoClientFramework:recv_cache_callback:receive_row_cache.length=" + receive_row_cache.length + ":" + DangoUtil.now2str()); }
- var arr:Array = receive_row_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.parse_notice(byte_array);
+ var crlf:String = "";
+ var temp_byta:ByteArray = new ByteArray;
+
+ socket.readBytes(receive_cache_byta, receive_cache_byta.length, socket.bytesAvailable); // データ読み込み
+
+ while(true){
+ // 長さ取得処理
+ if(receive_cache_do_phase == 0){
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:receive_cache_do_phase == 0:" + DangoUtil.now2str()); }
+ if(receive_cache_byta.length < 6){ break; } // 長さの読み込みが終わっていなければ
+
+ try{
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:receive_cache_do_phase == 0:start read"); }
+ receive_encode_type = receive_cache_byta.readByte(); // エンコードタイプ
+ receive_data_size = receive_cache_byta.readUnsignedInt(); // データサイズ
+ crlf = receive_cache_byta.readUTFBytes(1);
+
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:receive_encode_type=" + receive_encode_type); }
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:receive_data_size=" + receive_data_size); }
+
+ // receive_cache_bytaの不要な部分を削除
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:length=" + receive_cache_byta.length); }
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:position=" + receive_cache_byta.position); }
+
+ if(receive_cache_byta.length - receive_cache_byta.position > 0){
+ receive_cache_byta.readBytes(temp_byta, 0, receive_cache_byta.length - receive_cache_byta.position);
+ receive_cache_byta = temp_byta;
+ receive_cache_byta.position = 0;
+ } else {
+ receive_cache_byta = new ByteArray;
+ }
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:receive_cache_do_phase == 0:end read:length=" + receive_cache_byta.length); }
+
+ } catch(err:Error){
+ this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.IOError, "failed in DangoClientFramework:socket_read_push_cache:receive_cache_do_phase == 0"));
+ break;
+ }
+
+ receive_cache_do_phase = 1;
+ }
- 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"];
- var recv_server_time:String = receive_data[i]["server_time"];
-
- if(is_debug){ trace("DangoClientFramework:push recv_wait_do_cache:dango_" + notice_name + ": recv_c:" + recv_c + ":" + i + " recv_server_time:" + recv_server_time); }
- recv_wait_do_cache.push([notice_name, receive_data[i], recv_server_time, recv_do_count_no]);
-
- recv_do_count_no ++;
+ // データ取得処理
+ if(receive_cache_do_phase == 1){
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:receive_cache_do_phase == 1:" + DangoUtil.now2str()); }
+ if(receive_cache_byta.length < receive_data_size){ break; } // データの読み込みが終わっていなければ
+
+ try{
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:receive_cache_do_phase == 1:start read"); }
+ var recv_data:String = receive_cache_byta.readUTFBytes(receive_data_size); // データ取得
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:recv_data=" + recv_data); }
+
+ // データのパースと実行待ち受信キャッシュにデータを入れる
+ var ret_obj_data:Array;
+ if(recv_data != "" && recv_data != "\n"){ // データが空じゃないならdecode
+ ret_obj_data = JSON.decode(recv_data) as Array;
+ for(var i:uint = 0; i < ret_obj_data.length; i++){
+ var notice_name:String = ret_obj_data[i]["notice"];
+ var recv_server_time:String = ret_obj_data[i]["server_time"];
+
+ if(is_debug){ trace("DangoClientFramework:push recv_wait_do_cache:dango_" + notice_name + " i=" + i + " recv_server_time=" + recv_server_time); }
+ recv_wait_do_cache.push([notice_name, ret_obj_data[i], recv_server_time, recv_do_count_no]);
+ recv_do_count_no ++;
+ if(is_debug){ trace("DangoClientFramework:pushed recv_wait_do_cache:recv_do_count_no=" + recv_do_count_no); }
+ }
+ } else { // データが空なら空データを作ってreturn
+ if(is_debug){ trace("DangoClientFramework:ret_obj_data is empty." + DangoUtil.now2str()); }
}
- } else { // データが空なら
-// if(is_debug){ trace("DangoClientFramework:receive_data is empty." + DangoUtil.now2str()); }
- if(is_debug){ trace("DangoClientFramework:receive_data is empty."); }
+
+ // receive_cache_bytaの不要な部分を削除
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:length=" + receive_cache_byta.length); }
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:position=" + receive_cache_byta.position); }
+
+ if(receive_cache_byta.length - receive_cache_byta.position > 0){
+ receive_cache_byta.readBytes(temp_byta, 0, receive_cache_byta.length - receive_cache_byta.position);
+ receive_cache_byta = temp_byta;
+ receive_cache_byta.position = 0;
+ } else {
+ receive_cache_byta = new ByteArray;
+ }
+ if(is_debug){ trace("DangoClientFramework:socket_read_push_cache:receive_cache_do_phase == 1:end read:length=" + receive_cache_byta.length); }
+
+ } catch(err:Error){
+ this.dispatchEvent(new DangoErrorEvent("DangoError", DangoErrorCode.IOError, "failed in DangoClientFramework:socket_read_push_cache:receive_cache_do_phase == 1"));
+ break;
}
+ receive_cache_do_phase = 0;
}
}
+
}
/**
* recv_do_callback
* 受信データの実行する処理
@@ -321,11 +448,11 @@
*
* @param evt:TimerEvent
* @return void
*/
public function polling_callback(evt:TimerEvent):void {
- if(is_debug){ trace("DangoClientFramework:polling_callback:" + DangoUtil.now2str() ); }
+// 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();
@@ -346,12 +473,11 @@
/**
* delay_send_callback
* 遅延送信用タイマーコールバック
*
- * @param socket:Socket
- * @param send_obj:Object
+ * @param evt:TimerEvent
* @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); }
@@ -371,12 +497,13 @@
/**
* send data to server.
* クライアント側から使うサーバーへのデータ送信メソッド
*
- * @param socket:Socket
+ * @param action_name:String
* @param send_obj:Object
+ * @param delay:Boolean=false
* @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()); }
@@ -395,19 +522,18 @@
return(void);
}
// データをすぐ送信
this.send_data_to_server([send_obj_dup]);
- if(is_debug){ trace("DangoClientFramework:send_action:end:" + action_name + ":" + DangoUtil.now2str()); }
+// if(is_debug){ trace("DangoClientFramework:send_action:end:" + action_name + ":" + DangoUtil.now2str()); }
}
/**
* send data to server.
* フレームワーク側のデータ送信の一般処理
*
- * @param socket:Socket
- * @param send_obj:Object
+ * @param send_obj:Array
* @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)); }
@@ -440,112 +566,16 @@
// if(is_debug){ trace("DangoClientFramework:send_obj_str:" + send_obj_str + ":" + DangoUtil.now2str()); }
}
/**
- * receive data from server.
- * データ受信のデータのパースなど
- *
- * @return Object
- */
- public function parse_notice(byte_array:ByteArray):Array {
- if(is_debug){ trace("DangoClientFramework:parse_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 encode_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([]);
- }
- }
-
- /**
* dango_before_filter の雛形
* すべてのdango通知の前処理用のメソッド
- * over writeすべし
+ * オーバーライドして使うもの
*
* @param evt:DangoReceiveEvent
* @return void
+ */
protected function dango__before_filter(evt:Object):void {
}
- */
}
}