Advice for simple client/server application

Hello,

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.

Thanks for your time

Panagiotis (atmosx) Atmatzidis

email: [email protected]
URL: http://www.convalesco.org
GnuPG ID: 0xE736C6A0
gpg --keyserver x-hkp://pgp.mit.edu --recv-keys 0xE736C6A0

On 18/11/2012, at 10:09 AM, Panagiotis A. wrote:

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.

http is your friend

Henry

Subject: Advice for simple client/server application
Date: Sun 18 Nov 12 06:09:42AM +0900

Quoting Panagiotis A. ([email protected]):

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

[email protected]
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

Subject: Re: Advice for simple client/server application
Date: Sun 18 Nov 12 07:44:15PM +0900

Quoting Panagiotis A. ([email protected]):

So from what I understand, druby opens a connection and keeps it
alive until the client ends execution right?

From what I can see, Connection is closed either at end of the script
execution, or when the DRb instance is garbage-collected. There may
exist an explicit way to close a link without destroying the object,
but I have never needed such a thing. I would not keep idle links open
for long times. I’d either open a new instance each time I
need it, or maybe send keep-alive pings at regular intervals. It
really depends on the type of the application.

Carlo

Hello,

On 18 Νοε 2012, at 09:04 , Carlo E. Prelz [email protected] wrote:

(client_id, date, time, etc). The identification needs to be at very
clients. The server will make sure clients don’t get the same arrays
possible.
–8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<–
config={:verbose=>false,:SSLCertName=>CERTNAME}
def runme

end

end
For me, DRb has cut the cake several times (you can also base it on

ob.meth

  • K * Carlo E. Prelz - [email protected] che bisogno ci sarebbe
  •           di parlare tanto di amore e di rettitudine? (Chuang-Tzu)
    

Thanks for code sample and the extensive answer Carlo!

So from what I understand, druby opens a connection and keeps it alive
until the client ends execution right?

This approach could be a solution, thanks :slight_smile:

Panagiotis (atmosx) Atmatzidis

email: [email protected]
URL: http://www.convalesco.org
GnuPG ID: 0xE736C6A0
gpg --keyserver x-hkp://pgp.mit.edu --recv-keys 0xE736C6A0

Carlo, I came from a
link(http://www.ruby-forum.com/topic/4409293#1090107) to this. Seems
that first I need to fully understand how a client-server communication
work, I’ve never experienced with it. Can you recomend any material to
read or something? or do you think that simply learning DRb plus trial
and error is sufficient? what will be less painfull?

Subject: Re: Advice for simple client/server application
Date: Tue 25 Dec 12 02:20:48AM +0900

Quoting Dami??n M. Gonz??lez ([email protected]):

Carlo, I came from a
link(http://www.ruby-forum.com/topic/4409293#1090107) to this. Seems
that first I need to fully understand how a client-server communication
work, I’ve never experienced with it. Can you recomend any material to
read or something? or do you think that simply learning DRb plus trial
and error is sufficient? what will be less painfull?

The amount of increased understanding is directly proportional to the
amount of suffering involved :wink:

My personal experience of inter-process-communications is that of:

  1. talking between applications on a 300baud phone line…
  2. Using SystemV IPC
  3. chatting between unix sockets
  4. reading a bit about CoRBA and being disgusted about that
    committee-smacking stuff (I still have a book somewhere: anybody
    wants to buy it?)
  5. seeing the light with DRb.

Basically, with 1-3 you just send and receive bytes: you must
create and enforce your own more-or-less high-level protocols.

4 and 5 (as well as a myriad of other more or less successful
solutions that I was spared), on the other hand, are object-oriented
inter-process communications.

CoRBA pretended to be language-independent, and an awkward crock was
the result. DRb, on the other hand, is Ruby-only (and made in Japan
;-), so it is clean and straightforward.

I do not have tutorials to suggest, since I generally learn by
doing. But the nutshell is simple: from a process running here on my
PC I can invoke the methods of an object instantiated by a process
running in a toaster plugged to the internet in Waikaki, New Zealand,
in a transparent way. It is almost as if the two processes were the
same. The scope of the almost will only become clear to you with
experience.

Carlo

On Mon, Dec 24, 2012 at 7:15 PM, Carlo E. Prelz [email protected]
wrote:

    Subject: Re: Advice for simple client/server application
    Date: Tue 25 Dec 12 02:20:48AM +0900

The amount of increased understanding is directly proportional to the
amount of suffering involved :wink:

:slight_smile:

My personal experience of inter-process-communications is that of:

  1. reading a bit about CoRBA and being disgusted about that
    committee-smacking stuff (I still have a book somewhere: anybody
    wants to buy it?)

4 and 5 (as well as a myriad of other more or less successful
solutions that I was spared), on the other hand, are object-oriented
inter-process communications.

CoRBA pretended to be language-independent, and an awkward crock was
the result.

Sorry, I have to intervene here: CORBA does not deserve such a bad
reputation. It is language independent which naturally introduces
some level of complexity. But, for example, IIOP is pretty well done
since it especially allows for small message sizes - much smaller than
what is needed for a WebService SOAP request and response. For WAN
communication this is an advantage.

DRb, on the other hand, is Ruby-only (and made in Japan
;-), so it is clean and straightforward.

Well, to be fair it was written against a different set of
requirements. Especially the fact that no support for different
programming languages was needed made things significantly easier.
Plus, of course, the elegance of Ruby helped a lot in making DRb easy
to use and blend seamlessly with local functionality.

I do not have tutorials to suggest, since I generally learn by
doing. But the nutshell is simple: from a process running here on my
PC I can invoke the methods of an object instantiated by a process
running in a toaster plugged to the internet in Waikaki, New Zealand,
in a transparent way.

I’d love to see a picture of that toaster. :slight_smile:

It is almost as if the two processes were the
same. The scope of the almost will only become clear to you with
experience.

Basically the central question for distributed applications is: which
data is stored where and what do I need to transfer between processes.
Since remote method calls are much more expensive than in process
method calls people typically focus on reducing the number or
frequency of remote calls at the expense of more data being sent with
a single invocation.

Kind regards

robert

Okay, good explanation. Thank you Carlo for your time, very appreciated.

Hello,

On 18 Νοε 2012, at 09:04 , Carlo E. Prelz [email protected] wrote:

(client_id, date, time, etc). The identification needs to be at very
clients. The server will make sure clients don’t get the same arrays
possible.
–8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<–
config={:verbose=>false,:SSLCertName=>CERTNAME}
def runme

end

end
For me, DRb has cut the cake several times (you can also base it on

ob.meth

  • K * Carlo E. Prelz - [email protected] che bisogno ci sarebbe
  •           di parlare tanto di amore e di rettitudine? (Chuang-Tzu)
    

I’m playing with druby. Some concepts are hard to grasp for now. What
I’m trying to do is:

  1. Send results to server
  2. Run some methods with these results from the server
  3. Return the values to the server so it can perform the final
    operation.

I don’t get how can I get results from the client back to the server…?

How can I send back data to the server? :-/

Thanks

Panagiotis (atmosx) Atmatzidis

email: [email protected]
URL: http://www.convalesco.org
GnuPG ID: 0x1A7BFEC5
gpg --keyserver pgp.mit.edu --recv-keys 1A7BFEC5

Hello,

On 31 Μαϊ 2013, at 15:49 , Damián M. González [email protected]
wrote:

How can I send back data to the server? :-/

Depends, are you using the example given by Carlo? If not I will need
code to help.
[…]

Thanks for the reply. Here you can see a gist of the server
https://gist.github.com/atmosx/5686155

The server creates a list of words taken by a local MySQL server. Client
should take the list as an object
perform a series of action to the list and return an hash.

All I have now client-side is a simple client which access the server
object (Glucose.new) creates the hash
but I don’t know how to pass the hash back to the server and I can’t
find any examples on google.

Best Regards,

Panagiotis (atmosx) Atmatzidis

email: [email protected]
URL: http://www.convalesco.org
GnuPG ID: 0x1A7BFEC5
gpg --keyserver pgp.mit.edu --recv-keys 1A7BFEC5

How can I send back data to the server? :-/

Depends, are you using the example given by Carlo? If not I will need
code to help.