Subject: Advice for simple client/server application
Date: Sun 18 Nov 12 06:09:42AM +0900
Quoting Panagiotis Atmatzidis (atma@convalesco.org):
I need to write a client/server application and I'd like to some
advice from more experienced users.
There will be multiple clients and one server. Every client should
automatically identify to the server and give some details
(client_id, date, time, etc). The identification needs to be at very
basic level, just to avoid *strange things* from happening, since
the server is going to listen on the internet (firewall rules will
be applied, but some clients may have dynamic ip's, so some subnets
might be able to connect).
The server will dig for data from a database, at each client's
request will send an array (list of words) to the client. Then the
server will receive a hash with detailed info from the client about
the each element of the array and will dump the results into the
database. These arrays will be formed only when requested by
clients. The server will make sure clients don't get the same arrays
and make a check to the given results and that's about it.
It's a fairly simple application. I was thinking of using sinatra +
routes, to create the list in 'txt' format to the client but I'm not
sure how to send the results back to the sinatra server yet.
So I'd like to ask more advanced users if there's any protocol, gem
and/or framework that would make this task easier since I've never
done anything similar before. I know there's a variety of protocols
which can be used. I'd like to keep things simple & clean as much as
possible.
You do not specify if the clients are also written in Ruby. When I
have to do inter-process communications, on the same machine or
between remote machines, I use DRb (Distributed Ruby), which is
included in MRI. I certainly had to pour some sweat to gain confidence
with it, but it was worth the effort. You can even set it up to use
SSL, so the traffic will be encrypted.
Let's say you have a server based on this scaffold (engine.rb):
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
require 'drb/drb'
require 'drb/ssl'
class Engine
HOST='yourhost.xxx'
PORT=21212
URI="drbssl://#{HOST}:#{PORT}"
CERTNAME=[['C',HOST.split('.')[-1]],['O',HOST],['CN',self.to_s]]
def initialize
config={:verbose=>false,:SSLCertName=>CERTNAME}
@srv=DRb::start_service(URI,self,config)
#
# Your inits
#
@para1=rand(1000)
@para2=rand(1000)
end
def runme
DRb::thread.join()
end
#
# Remote-callable methdos
#
def method1(a)
"#{@para1} #{@para2} method 1 returns #{a.to_s}"
end
def method2(a)
"#{@para1} #{@para2} method 2 returns #{a.to_s} #{a.to_s}"
end
def Engine::remote
config={:verbose=>false}
DRb.start_service(nil,nil,config)
DRbObject.new(nil,URI)
end
end
if($0==__FILE__)
Engine::new.runme
end
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
Your client may be something like this:
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
require 'engine.rb'
class Client
def initialize
@engine=Engine::remote
end
def runme
puts @engine.method1(rand(1000))
puts @engine.method1('test')
puts @engine.method2(rand(1000))
puts @engine.method2('test')
end
end
Client::new.runme
--8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<--
Your engine can provide an identify method (you may have a hash of
user ids/passwords associated to one or more address, for
example). Then, you would have a 'dig' method that would provide the
desired list of words.
For me, DRb has cut the cake several times (you can also base it on
Unix sockets, for intra-machine communications).
There are some snags. The biggest is that methods of the DRb-exported
objects are executed remotely, but if your client receives remote
objects, it will receive LOCAL COPIES of them. Let's say your engine
has object @ob, which has method meth. If your engine has this method
def m
@ob.meth
end
meth is executed remotely, by the engine process. But if your
methods just returns @ob:
def m
@ob
end
and in your client you have
ob=@engine.m
ob.meth
meth is executed in the client's thread (and thus, for example, it
won't be able to access the database opened by the remote engine).
I hope this is of help.
Carlo
--
* Se la Strada e la sua Virtu' non fossero state messe da parte,
* K * Carlo E. Prelz - fluido@fluido.as che bisogno ci sarebbe
* di parlare tanto di amore e di rettitudine? (Chuang-Tzu)
So from what I understand, druby opens a connection and keeps it alive until the client ends execution right?