我正在尝试创建一个简单的客户端-服务器应用程序。我遇到了DRuby,我尝试了一下。看起来真的很好,但我不确定是否允许双向通信。
我想要的功能如下:
- 服务器开始使用对象运行服务客户端。
- 客户端连接到服务器,获取对象。
- 客户端将它自己的对象返回给服务器。
在不向客户端打开端口(变成服务器)的情况下,这第 3 步是否可行?
问候,
您可以在服务器中创建一个接口,因此当客户端连接到它时,可以更改服务器中的某些状态(传递它自己的对象)。
请参阅此代码:
服务器.rb
require 'drb'
class Server
attr_accessor :object
def initialize()
@object = {:id => 'from server side'}
end
end
server = Server.new
DRb.start_service('druby://localhost:1992', server)
puts DRb.uri
begin
DRb.thread.join
rescue Exception
Process.kill("TERM", Process.pid)
end
客户端.rb
require 'drb'
@server = DRbObject.new(nil, "druby://localhost:1992")
DRb.start_service
puts @server.object
@server.object = {:id => "from client side"}
puts @server.object
输出是:
{:id=>"from server side"}
{:id=>"from client side"}
此外,DRuby
实现了观察者模式,因此您可以使您的服务器可观察,包括DRb::DRbObservable
类 Server 中的模块。然后实现notify
通知所有观察者的方法,传递可以序列化的对象(包括include DRb::DRbUndumped
)。在客户端,我们可以将观察者添加到服务器并实现方法更新来处理通知,请参见以下示例:
服务器.rb
require 'drb'
require 'drb/observer'
class Server
include DRb::DRbObservable
attr_accessor :object
def initialize()
@object = {:id => 'from server side'}
end
def do_something
notify(Message.new("this is a notification"), Message.new("other notification"))
end
def notify(*args)
changed
notify_observers(*args)
end
class Message
include DRb::DRbUndumped
attr_reader :message
def initialize(message)
@message = message
end
end
end
server = Server.new
DRb.start_service('druby://localhost:1992', server)
puts DRb.uri
begin
DRb.thread.join
rescue Exception
Process.kill("TERM", Process.pid)
end
客户端.rb
require 'drb'
class MyObserver
include DRbUndumped
def update(*notifications)
puts "checking notifications ..."
notifications.each do |n|
puts n.message
end
end
end
@server = DRbObject.new(nil, "druby://localhost:1992")
DRb.start_service
@server.add_observer(MyObserver.new)
puts @server.object
@server.object = {:id => "from client side"}
puts @server.object
@server.do_something
输出是:
{:id=>"from server side"}
{:id=>"from client side"}
checking notifications ...
this is a notification
other notification