From: Hidetoshi NAGAI Date: 2009-07-02T17:18:59+09:00 Subject: [ruby-list:46139] Re: 足し算ゲームサーバー 永井@知能.九工大です. From: 牛坂 博則 Subject: [ruby-list:46136] 足し算ゲームサーバー Date: Thu, 2 Jul 2009 13:19:44 +0900 Message-ID: <4A4C3533.3050502@aecl.ntt.co.jp> > 牛坂ともうします。"ruby アプリケーションプログラム"を勉強中です。このな > かの5.6.5章の1対1の非同期通信のところをいま取り組んでいます。 その部分の著者です. > serverを立 > ち上げて接続しても、途中で止まってしまいます。ちなみにwindows XP上でコマ > ンドプロンプトより実行しています。 原因は,なかむら(う)さんがおっしゃった通りだと思います. 執筆時点では Linux 環境でやってたので, 当時は Win 環境でのその問題に気付いていませんでした. ごめんんさい. それだけでは何なので,応急処置的な対策を少々. 同書を使っての勉強中であれば, もしかすると Ruby/Tk も動く環境になさっているかもしれません. そうであるなら,コマンドプロンプトの代わりに Ruby/Tk で作ったダミーのコンソールを使うことで ある程度までは回避できると思います. # コマンドプロンプト上での入力を使いませんので, # thread 切替えをブロックしないはずです. 以下にソースを示します. この DummyCons は手抜きで作成したものなので,細かい問題が多々存在する上, クライアントスクリプトで使っていた print と gets にしか対応していません. $stdin, $stdout, $stderr に設定できる程度の汎用的なものにするには もうちょっとまじめに頑張る必要があります. ------------------------------------------- require 'tk' class DummyCons def initialize @v = TkVariable.new f = TkFrame.new.pack(:fill=>:x) TkLabel.new(f, :text=>'>> ').pack(:side=>:left) TkButton.new(f, :text=>'reset EOF', :command=>proc{reset}).pack(:side=>:right) @e = TkEntry.new(f).pack(:side=>:left, :fill=>:x, :expand=>true) @t = TkText.new(:takefocus=>false).pack(:expand=>true, :fill=>:both) @st = "" @e.bind('Return'){ s = @e.value; @e.value = "" @t.insert(:end, "#{s}\n") @v.value = s } eof_ev = TkVirtualEvent.new('Control-z','Control-d','Destroy') @e.bind(eof_ev){@st = false; @v.value = ""} @e.focus @th = Thread.new{Tk.mainloop} end def print(s) begin @t.insert(:end, s) @t.see(:end) rescue # ignore error end end def gets @v.wait if @st (@st)? @v.value: nil end def reset if @th.status @st = true self else raise RuntimeError, "#{self.inspect} is already destroyed" end end end cons = DummyCons.new # ↑ここまでがダミーコンソール # # ↓ここからがクライアントプログラムをちょっとだけいじったもの # "print msg" を "cons.print msg" に, # "STDIN.gets" を "cons.gets" に変更している require 'socket' #STDOUT.sync = true host = if ARGV[0] then ARGV[0] else 'localhost' end port = if ARGV[1] then ARGV[1] else 12345 end socket = TCPSocket.open(host, port) th_get = Thread.start { while msg = socket.gets # print msg cons.print msg end } th_ans = Thread.start { # while msg = STDIN.gets while msg = cons.gets socket.write msg end #sock.shutdown(1) } th_get.join th_ans.exit if th_ans.alive? socket.close ------------------------------------------- -- 永井 秀利 (nagai@ai.kyutech.ac.jp) 九州工業大学 大学院情報工学研究院 知能情報工学研究系 知能情報メディア部門