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::DefaultDataType, DangoFrameworkModule::MaxLen

Instance Attribute Summary collapse

Attributes included from DangoFrameworkModule

#dango_logger

Instance Method Summary collapse

Methods included from DangoFrameworkModule

#dango_receive_data, #dango_send_data, #debug_print, #logger

Methods included from ErrorMessage

#error_message

Constructor Details

#initialize(env, config = nil) ⇒ DangoClientFramework

メイン処理



33
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
# File 'lib/dango/client_framework.rb', line 33

def initialize(env, config = nil)
  if !config
    config = YAML.load(open("#{RAILS_ROOT}/dango/config/#{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  # 未定義時にこのログレベルになる
  
  @recv_count = 0 # 受信回数
  @send_count = 0 # 送信回数
  
  Signal.trap('INT') do # SIGINT を捕捉する。
    puts "shutdown"
#     exit
    exit!
  end
  
  dango_client_init() # 初期設定読み込み
  
  @log_file = @connection_client_log_file
  @log_level = @connection_client_log_level
  @log_max_size = 1048576
  @log_shift_age = 99
  
  # loggerの準備
  logger.debug("-------client initialize host=#{@connection_client_host} port=#{@connection_client_port}")
  
  # データ送受信用の共有メモリ初期化
  send_return_shared_init()
  @send_receive_mutex = Mutex.new # 送受信用の排他処理
  
  # 通知共有メモリの初期化
  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 DangoFrameworkConnectionError
  end
  
  @sock.binmode
  @sock.sync = true
  logger.debug("addr:#{@sock.addr.inspect}")
  
  @tmutex = Mutex.new # sockの排他処理用
  
  dango_heart_beat_thread_init() # ハートビート送信スレッドの起動
  
  @sid = nil # 接続して決まるsidを保持
  
  # データ受信用のスレッドの開始
  @thread_receive = Thread.start{ thread_main() }
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

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

Raises:

  • (NameError)


187
188
189
190
# File 'lib/dango/client_framework.rb', line 187

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

Instance Attribute Details

#sidObject (readonly)

Returns the value of attribute sid.



98
99
100
# File 'lib/dango/client_framework.rb', line 98

def sid
  @sid
end

Instance Method Details

#dango_client_closeObject

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



193
194
195
# File 'lib/dango/client_framework.rb', line 193

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

#dango_client_initObject

起動処理



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

def dango_client_init
end

#dango_client_notice_sharedObject

通知共有メモリ



314
315
316
# File 'lib/dango/client_framework.rb', line 314

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

#dango_client_notice_shared_initObject

通知共有メモリの初期化



310
311
312
# File 'lib/dango/client_framework.rb', line 310

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

#dango_client_receive_decrypt(str) ⇒ Object

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



225
226
227
# File 'lib/dango/client_framework.rb', line 225

def dango_client_receive_decrypt(str) # 継承用
  str
end

#dango_client_send_encrypt(str) ⇒ Object

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



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

def dango_client_send_encrypt(str) # 継承用
  str
end

#dango_heart_beat_thread_initObject

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



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/dango/client_framework.rb', line 153

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

ハートビートなら



183
184
# File 'lib/dango/client_framework.rb', line 183

def dango_receive__heart_beat(rec_obj)
end

#dango_receive__notice_sid(rec_obj) ⇒ Object

接続直後のsid通知なら



174
175
176
# File 'lib/dango/client_framework.rb', line 174

def dango_receive__notice_sid(rec_obj)
  @sid = rec_obj["_sid"]
end

#dango_receive__notice_system_message(rec_obj) ⇒ Object

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



179
180
# File 'lib/dango/client_framework.rb', line 179

def dango_receive__notice_system_message(rec_obj)
end

#dango_receive_decrypt(str) ⇒ Object

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



228
229
230
# File 'lib/dango/client_framework.rb', line 228

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

#dango_send_encrypt(str) ⇒ Object

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



220
221
222
# File 'lib/dango/client_framework.rb', line 220

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

#dango_session_closedObject

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



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

def dango_session_closed
end

#send_action(action_name, send_obj) ⇒ Object

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



233
234
235
236
237
238
# File 'lib/dango/client_framework.rb', line 233

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"] = 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秒



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/dango/client_framework.rb', line 245

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.synchronize 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(DangoFrameworkTimeoutError, "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(DangoFrameworkError, "received data is none") 
    end
    
    send_return_shared[action_name]
  end
end

#send_return_sharedObject



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

def send_return_shared
  @send_return_shared
end

#send_return_shared_initObject

send_action_return_notice用の共有メモリ



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

def send_return_shared_init
  @send_return_shared = SharedMemoryStore.new
end