Class: DangoClientFramework

Inherits:
Object show all
Includes:
DangoFrameworkModule
Defined in:
lib/dango/client_framework.rb

Overview

フレームワーククラス

Direct Known Subclasses

DangoMonitorClient, TestClient

Defined Under Namespace

Classes: ClientNoticeShared

Constant Summary collapse

SendReceiveSleepIntervalSec =

データ送信後の順の際のタイムアウトチェック間隔秒

0.1
HeartBeatSendIntervalSec =

ハートビート送信の間隔秒

5.0

Constants included from DangoFrameworkModule

DangoFrameworkModule::CommMaxDigit, DangoFrameworkModule::DefaultEncodeType, DangoFrameworkModule::EncodeTypeJSON, DangoFrameworkModule::EncodeTypeMarshal, DangoFrameworkModule::EncodeTypeYAML, DangoFrameworkModule::MaxLenRecv, DangoFrameworkModule::MaxLenSend, DangoFrameworkModule::ReadTimeoutSec

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from DangoFrameworkModule

#dango_receive_data, #dango_send_data, #debug_print, #error_print

Methods included from DangoLoggerModule

#logger

Methods included from ErrorMessage

#error_message

Constructor Details

#initialize(env, config = nil) ⇒ DangoClientFramework

メイン処理



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/dango/client_framework.rb', line 34

def initialize(env, config = nil)
  if !config
    config = YAML.load(open("#{RAILS_ROOT}/config/dango/#{env}.yml", "rb"){|fh| fh.read})
  end
  
  @config = config
  
  # 変数の初期設定
  @connection_client_host = @config['network']['host'] || 'localhost'
  @connection_client_port = @config['network']['port'] || 15000
  
  @connection_client_log_file       =    ""              # 未定義時にこのログファイル名を使う
#    @connection_client_log_level      = Logger::DEBUG  # 未定義時にこのログレベルになる
  @connection_client_log_level      = Logger::INFO   # 未定義時にこのログレベルになる
  @connection_client_log_max_size   = 1048576   # 未定義時にこのログレベルになる
  @connection_client_log_shift_age  = 99   # 未定義時にこのログレベルになる
  
  @connection_encode_type = EncodeTypeMarshal
  
  @recv_count = 0        # 受信回数
  @send_count = 0        # 送信回数
  @recv_byte = 0         # 受信バイト数
  @send_byte = 0         # 送信バイト数
  
  Signal.trap('INT') do # SIGINT を捕捉する。
    puts "shutdown"
#     exit
    exit!
  end
  
  begin
    dango_client_init() # 初期設定読み込み
  rescue
    message = "failed in dango_client_init. #{error_message($!, 'u')}"
    logger.error message
    raise DangoFrameworkException, message
  end
  
  @log_file      = @connection_client_log_file
  @log_level     = @connection_client_log_level
  @log_max_size  = @connection_client_log_max_size
  @log_shift_age = @connection_client_log_shift_age
  
  # loggerの準備
  logger.info("-------client initialize")
  logger.info("host=#{@connection_client_host} port=#{@connection_client_port}")
  logger.info("@log_file      = #{@log_file}")
  logger.info("@log_level     = #{@log_level}")
  logger.info("@log_max_size  = #{@log_max_size}")
  logger.info("@log_shift_age = #{@log_shift_age}")
  
  # データ送受信用の共有メモリ初期化
  send_return_shared_init()
  @send_receive_mutex = DangoMutex.new(:send_receive_mutex) # 送受信用の排他処理
  
  # 通知共有メモリの初期化
  dango_client_notice_shared_init()
  
  # ソケットの準備
  @sock = nil
  @is_close = false
  
  # サーバーへ接続
  begin
    @sock = TCPSocket.new(@connection_client_host, @connection_client_port)
  rescue Errno::EBADF, Exception
    raise DangoFrameworkConnectionException
  end
  
  @sock.binmode
  @sock.sync = true
  logger.debug("addr:#{@sock.addr.inspect}")
  
  @tmutex = DangoMutex.new(:tmutex) # sockの排他処理用
  
  dango_heart_beat_thread_init() # ハートビート送信スレッドの起動
  
  @sid = nil # 接続して決まるsidを保持
  
  # データ受信用のスレッドの開始
  @thread_receive = Thread.start{ thread_main() }
  
  # エンコードタイプ変更を送信
  send_obj = {"encode_type" => @connection_encode_type}
  send_action("_change_encode_type", send_obj)
  logger.info "_change_encode_type=#{@connection_encode_type.inspect}"
  
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

必要に応じて追加するメソッド

Raises:

  • (NoMethodError)


216
217
218
219
# File 'lib/dango/client_framework.rb', line 216

def method_missing(name, *args)
  logger.info "method not found. #{name.inspect} #{args.inspect}"
  raise(NoMethodError, "method not found. #{name.inspect} #{args.inspect}")
end

Instance Attribute Details

#sidObject (readonly)

Returns the value of attribute sid.



123
124
125
# File 'lib/dango/client_framework.rb', line 123

def sid
  @sid
end

Instance Method Details

#dango_client_closeObject

ユーザーが終了させたい時に呼び出すメソッド(セッションを切る)



222
223
224
# File 'lib/dango/client_framework.rb', line 222

def dango_client_close
  client_quit() # クライアントの終了処理
end

#dango_client_initObject

起動処理



26
27
# File 'lib/dango/client_framework.rb', line 26

def dango_client_init
end

#dango_client_notice_sharedObject

通知共有メモリ



343
344
345
# File 'lib/dango/client_framework.rb', line 343

def dango_client_notice_shared # 通知共有メモリ
  @client_notice_shared
end

#dango_client_notice_shared_initObject

通知共有メモリの初期化



339
340
341
# File 'lib/dango/client_framework.rb', line 339

def dango_client_notice_shared_init # 通知共有メモリの初期化
  @client_notice_shared = ClientNoticeShared.new(self)
end

#dango_client_receive_decrypt(str) ⇒ Object

クライアントの復号化処理



254
255
256
# File 'lib/dango/client_framework.rb', line 254

def dango_client_receive_decrypt(str) # 継承用
  str
end

#dango_client_send_encrypt(str) ⇒ Object

クライアントの暗号化処理



246
247
248
# File 'lib/dango/client_framework.rb', line 246

def dango_client_send_encrypt(str) # 継承用
  str
end

#dango_heart_beat_thread_initObject

ハートビート送信スレッドの起動



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/dango/client_framework.rb', line 181

def dango_heart_beat_thread_init
  th = Thread.start do
    loop do
      begin
        sleep HeartBeatSendIntervalSec
        
        if @sock && ! @sock.closed?
          logger.debug "dango_heart_beat_thread_init:send _notice_heart_beat:"
          
          send_action("_notice_heart_beat", {})
        end
        
      rescue
        logger.error "Exception dango_heart_beat_thread_init  #{error_message($!, 'u')}"
      end
    end
  end
  th.priority = 1
end

#dango_receive__heart_beat(rec_obj) ⇒ Object

ハートビートなら



212
213
# File 'lib/dango/client_framework.rb', line 212

def dango_receive__heart_beat(rec_obj)
end

#dango_receive__notice_sid(rec_obj) ⇒ Object

接続直後のsid通知なら



202
203
204
205
# File 'lib/dango/client_framework.rb', line 202

def dango_receive__notice_sid(rec_obj)
  @sid = rec_obj["_sid"]
  logger.info "sid=#{@sid}"
end

#dango_receive__notice_system_message(rec_obj) ⇒ Object

システムからのメッセージ通知なら



208
209
# File 'lib/dango/client_framework.rb', line 208

def dango_receive__notice_system_message(rec_obj)
end

#dango_session_closedObject

セッションが切れると呼ばれる処理



30
31
# File 'lib/dango/client_framework.rb', line 30

def dango_session_closed
end

#receive_decrypt(str) ⇒ Object

フレームワークから呼ばれる部分



257
258
259
# File 'lib/dango/client_framework.rb', line 257

def receive_decrypt(str) # フレームワークから呼ばれる部分
  dango_client_receive_decrypt(str)
end

#send_action(action_name, send_obj) ⇒ Object

クライアントからサーバーへのデータ送信



262
263
264
265
266
267
# File 'lib/dango/client_framework.rb', line 262

def send_action(action_name, send_obj)
  logger.debug "send_action(#{action_name.inspect}, #{send_obj['_id']}) "
  send_obj_dup = send_obj.dup
  send_obj_dup["_action_name"] = action_name.to_s
  dango_send_data(@sock, [send_obj_dup])
end

#send_action_return_notice(action_name, send_obj, options = {}) ⇒ Object

サーバーからクライアントへのデータ送信 自動でreturn_nameに対応したdango_receive_メソッドが出来上がるので注意 options = {:return_name=> :timeout => } return_nameは省略時は、action_nameの頭にreturnを付けたもののシンボルになる timeoutは省略時は6秒



274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/dango/client_framework.rb', line 274

def send_action_return_notice(action_name, send_obj, options = {})
#    logger.debug "send_action_return_notice(#{action_name.inspect})"
#    logger.debug "send_action_return_notice(#{action_name.inspect}, #{send_obj.inspect}, #{options.inspect})"
  
  return_name = options[:return_name] || ("return_" + action_name.to_s).to_sym
  timeout = options[:timeout] || 6
  
  @send_receive_mutex.timeout_sync(10, :send_return) do
    send_return_shared[action_name] = nil
    
    receive_thread = nil
    end_reserved_time = Time.now + timeout
    
    # 戻ってきたデータのチェック
    action_name_sym = (action_name.class == Symbol) ? (":"+action_name.to_s) : ('"'+action_name+'"')
    instance_method_name = "dango_receive_#{return_name}"
    expr = <<-EOF
      def self.#{instance_method_name}(ret_obj)
#          logger.debug "ret_obj:" + ret_obj.inspect
        send_return_shared[#{action_name_sym}] = ret_obj
      end
    EOF
    instance_eval expr
    
    # タイムアウトチェック
    (timeout.to_f / SendReceiveSleepIntervalSec).to_i.times do
      raise(DangoFrameworkTimeoutException, "timeout:#{action_name}") if Time.now > end_reserved_time
      
      # 送信スレッドが開始していなければ開始
      if !receive_thread
        receive_thread = Thread.start(action_name, send_obj) do
          send_action(action_name, send_obj)
        end
      end
      
      # 戻ってきたデータがあれば
      if send_return_shared[action_name]
        logger.debug "action_name:#{send_return_shared[action_name].inspect}"
        break 
      end
      
      sleep SendReceiveSleepIntervalSec # スリープ
    end
    
    if !send_return_shared[action_name] # 戻ってきたデータがあるかどうかチェック
      raise(DangoFrameworkException, "received data is none") 
    end
    
    send_return_shared[action_name]
  end
end

#send_encrypt(str) ⇒ Object

フレームワークから呼ばれる部分



249
250
251
# File 'lib/dango/client_framework.rb', line 249

def send_encrypt(str) # フレームワークから呼ばれる部分
  dango_client_send_encrypt(str)
end

#send_return_sharedObject



21
22
23
# File 'lib/dango/client_framework.rb', line 21

def send_return_shared
  @send_return_shared
end

#send_return_shared_initObject

send_action_return_notice用の共有メモリ



18
19
20
# File 'lib/dango/client_framework.rb', line 18

def send_return_shared_init
  @send_return_shared = SharedMemoryStore.new({})
end