About Legs¶ ↑
This is Legs, the little networking doodad somewhat inspired by Camping but not all that much really. It uses a lot of ruby trickery to give you one class, Legs, which can act as a server, a client, or a peer depending on how you use it. Oh, and the protocol it uses is JSON-RPC 1.0, so quite platform and language agnostic. :)
If you give Legs some methods, then anyone you connect to will be able to make calls back to those methods to notify you of things. Otherwise, your instance of legs will only be able to connect out to a legs server and call methods in that server, but not the other way around. If that’s all you need, learning Camping and using http might be a better way to go, as http is a more popular and more standard protocol. :)
To connect to a Legs server running on your own computer¶ ↑
server = Legs.new - OR - server = Legs.new('localhost')
To connect to a remote server¶ ↑
server = Legs.new('web.address.to.server')
To connect to a server on port 1234¶ ↑
server = Legs.new('web.address', 1234)
To create a legs server¶ ↑
Legs.start do def callable_method(a, b, c = 'default') return "You called with params #{a}, #{b}, and #{c}" end end sleep # Stops ruby from closing as soon as Legs starts. # don't put sleep if you're embedding the server in a shoes UI or something.
To add methods to legs, without creating a server¶ ↑
Legs.start(false) do def callable_method(a, b, c = 'default') return "You called with params #{a}, #{b}, and #{c}" end end
You should do this before creating instances of Legs with Legs.new. Adding methods like this is useful, because the “TCP” network connections Legs makes work in both directions, so if you have some methods, server’s you connect to will be able to call your methods to notify you of events and stuff. If you don’t give it false
on that first line, it will start up a server as well, so other instances of Legs can connect in to you, deliciously peery. It’s important to know, though, that the Legs.users
only includes connections who connected to you, not outgoing connections you make with Legs.new syntax. You could make your own array of outgoing connections to keep track ot them if you want. :)
Inside of your Legs.start block, there are two magic methods you can use in your code, these are server
and caller
. server
references the Legs server object, which has methods like users
and some other stuff you can use to your advantage. The caller
method gives you the Legs instance representing that network connection (doesn’t matter if they connected to you or vice versa).
Legs instances, like the one you get from caller
, and the array of them you get from server.users
have a useful method called meta
which gives you a hash you can store whatever you like inside of. Things you might put in there include the user’s name, or if they have any special powers, so you can control which methods they can use and what they can do. Here’s an example: :)
Legs.start do def count caller.meta[:counter] ||= 0 caller.meta[:counter] += 1 end end sleep
When you connect to this server, you can call the count
method. Each time you call it, it will give you a number, starting with 1 and growing higher each time. Because it stores the ‘counter’ in the caller’s meta hash, if another person connects, they will start out with the number 1 as well. You could connect to this with :)
server = Legs.new('localhost') puts "#{server.count}, #{server.count}, #{server.count}"
And if you run that script, you should see in your terminal: “1, 2, 3”. That’s pretty much how Legs works. An instance of legs has a few of it’s own special methods: close!
, notify!
, send!
, send_async!
, connected?
, socket
, parent
, meta
, and send_data!
. If you need to actually run a method on your server with one of these names, do: server.send!(:connected?, a_param, another_param)
or whatever, and it’ll run that method on the server for you. If you want to let the server know something, but don’t care about the method’s response, or any errors, you can do the same thing with legs.notify!
, which will make your program run faster, especially if it’s running through the web. :)
Finally, if you’re making a program for running over the internet, and want to make your app more responsive, you can call methods asyncronously. What this means is that the method won’t return immidiately, but instead will send the request out to your network, and your program will continue to run, and then when the server responds, a block you provide will be run. The block is passed an object, call that object’s result
or value
method to get the server response, or it will raise an error if the server had an error, so you can use it as though it were a syncronous response. Error is only raised the first time you call it. To do this, just give the thing a block like this: server.some_method { |result| ... do stuff with result.value ... }
.