Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


tango is a small, simple and customizable RPC (remote procedure call) module for Lua.

Its main features are:

  • a generic transparent proxy for call invocations
  • support of remote objects (tables with functions, userdata etc, see tango.ref)
  • a generic dispatch routine for servers
  • several server implementations for different protocols, message formats and event/io frameworks, further called backends
  • several client implementations for different protocols and message formats

Backends included

Tutorial (copas_socket server + socket client)


The greet server code

-- load tango module
local tango = require'tango'
-- define a nice greeting function
greet = function(...)
-- start listening for client connections        
  port = 12345

The client code calling the remote server function greet

-- load tango module
local tango = require'tango'
-- connect to server
local con = tango.client.socket.connect{
   address = 'localhost',
   port = 12345
-- call the remote greeting function

Access anything?

Since the server exposes the global table _G per default, the client may even directly call print,let the server sleep a bit remotely (os.execute) or calc some stuff (math.sqrt).

-- variable argument count is supported
-- any function or variable in the server's _G can be accessed by default        
con.os.execute('sleep 1')

One can limit the server exposed functions by specifying a functab like this (to expose only methods of he math table/module):

local tango = require'tango'
-- just pass a table to the functab to limit the access to this table
  port = 12345,
  functab = math

As the global table _G is not available any more, the client can only call methods from the math module:


Remote Variables

Sometimes you need to get some data from the server, as enumaration-like-constants for instance. Instead of creating a mess of remote getters and setters, just treat the value of interest as a function...

Let's read the remote table friends from the server

local tango = require'tango'
-- connect to server as usual
local con = tango.client.socket.connect()
-- friends is a remote table but could be of any other type
local friends = con.friends()

To change the servers state, just pass the new value as argument:

local tango = require'tango'
local con = tango.client.socket.connect()
-- read the remote variable
local friends = con.friends()
-- modify it 
-- and write back the new value

If you are worried about security concerns, just do not allow read and/or write access:

local tango = require'tango'
-- write_access and read_access can be set independently
-- accessing variables from the client side will now cause errors.
  write_access = false,
  read_access = false

Using classes/tables/objects remotely (tango.ref)

Even if Lua does not come with a class model, semi-object-oriented programming is broadly used via the semicolon operator, e.g.:

-- assume you open a pipe locally
local p = io.popen('ls')
-- and read some stuff from it, ... note the : operator
local line = p:read('*l')

To allow such construct remotely via tango, one has to use the tango.ref:

local con = tango.client.socket.connect()
-- pass in the remote function and all arguments required (optionally)
local p = tango.ref(,'ls')
-- now proceed as if p was a local object
local line = p:read('*l')
-- unref it locally to let the server release it

This may seem a bit awkward, but it is certainly less hassle, then writing non-object-oriented counterparts on the server side.


You can run test by the following sh call in the project root directory:


tango does not need to be installed.

Client/Server compatibilities



tango provides a default (lua-only) table serialization which should meet most common use cases.

Anyhow, the table serialization is neither exceedingly fast nor compact in output or memory consumption. If this is a problem for your application, you can customize the serialization by assigning your serialize/unserialize methods to the clients and servers respectively.

Socket client with customized serialization:

local tango = require'tango'
local cjson = require'cjson'
-- set serialization on the client side
local con = tango.client.socket.connect{
   serialize = cjson.encode,
   unserialize = cjson.decode

Copas socket server with customized serialization:

local tango = require'tango'
local cjson = require'cjson'
-- set serialization on the server side
   serialize = cjson.encode,
   unserialize = cjson.decode

Some alternatives are:


The requirements depend on the desired i/o backend, see the corresponding rockspecs for details.


With LuaRocks: Directly from the its repository:

 $ sudo luarocks install tango-copas

or tango-complete, which requires lua-zmq and lua-ev (and the corresponding C-libs:

 $ sudo luarocks install tango-complete

or a specific rock from

 $ sudo luarocks install

Note: luarocks must be >= and requires luasec for doing https requests!

 $ sudo apt-get install libssl-dev
 $ sudo luarocks install luasec


A simple and transparent RPC module for Lua.




No packages published