Skip to content

Instantly share code, notes, and snippets.

@makoto
Created August 20, 2011 12:09
Show Gist options
  • Save makoto/1159019 to your computer and use it in GitHub Desktop.
Save makoto/1159019 to your computer and use it in GitHub Desktop.
drubyコラム: DRb.start_serviceのなぞ (4.1.3 どちらがサーバでどちらがクライアント?)

今までの章ではクライアント側からサーバ側に接続する時にも「DRb.start_service」とDRbサーバを立ち上げていましたが、不思議に思われたことはないでしょうか?

DRb.start_service
DRbObject.new_with_uri('druby://:1234')

DRb.start_serviceはなくてもリモートオブジェクトから値をとってくる事はできます。

irb(main):015:0> h = DRbObject.new_with_uri('druby://:1234')
=> #<DRb::DRbObject:0x10031cd00 @ref=nil, @uri="druby://:1234">

  irb(main):013:0> h   => #<DRb::DRbObject:0x100348c98 @ref=nil, @uri="druby://:1234">   irb(main):014:0> h['a']   => 1

ではわざわざなぜDRb.start_serviceを指定しているか。これは「参照渡し」を考えると理解できます。まずは上のハッシュをmapメソッドでイタレートしてみましょう。

irb(main):018:0> h.map{|a| a}
DRb::DRbConnError: DRb::DRbServerNotFound
	from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1658:in `current_server'
	from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/drb/drb.rb:1726:in 

おや。DRb::DRbServerNotFoundというメッセージが出てきましたね。これは実はmapというメソッドが返してくるEnumeratorオブジェクトはMarshal.dump出来ないために参照渡しをします。そのためサーバー側でイタレートしているつもりが実はクライアントサーバ側でイタレートする必要があるのですが、クライアント自身のサーバが立ち上がっていないために先ほどのようなエラーがでてきたのです。

irb(main):019:0> DRb.start_service
irb(main):020:0> h.map{|a| a}
=> [["a", 1]]

クライアントサイドでサーバを立ち上げてからもう一度試して下さい。今度は上手くいきましたね。こういった事態を避けるために、クライアント側がサーバ側に接続するときも常に「DRb.start_service」をしておくのをお勧めします

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment