-
Notifications
You must be signed in to change notification settings - Fork 19
Home
BJSONRPC (Bidirectional JSON-RPC) is a JSON-RPC implementation in pure python aimed at speed and simplicity.
It's a good replacement to XML-RPC in environments where interactivity is critical.
It follows the JSON-RPC 1.1 specification with several additions.
Currently in development stage. Is fully functional, but API may change.
A beta version will probably be released over February.
-
Implemented in pure python
-
TCP/IP Socket based. There is no HTTP version.
-
Connections are permanent and reused for multiple calls.
-
Low bandwith use. (aprox 60 bytes or less per call)
-
Minimal network latency. (with asyncronous calls is possible to use the full bandwith)
-
Methods can be stateful (they can remember what you called before, etc)
-
Allows (and simplifies) asynchronous calls.
-
Event-driven client and server (can be run with no threads at all)
-
Allows keyword parameters to be passed to functions.
-
Bidirectional. Client can also publish methods for server.
-
Object Oriented Programming (OOP). Objects can be created and handled remotely.
-
Client/Server Object Reference. You can create a object in the other end and tell some method to use it.
-
Server Method Reference. You can pass a server method as a parameter to a server function.
import bjsonrpc
class MyHandler(bjsonrpc.BaseHandler):
def add(self,a,b): return a+b
bjsonrpc.server(handler_factory=MyHandler).serve()
import bjsonrpc
conn = bjsonrpc.connect() # defaults to 127.0.0.1:10123
print conn.call.add(2,3) # prints 5
There are some requests in their raw state over the socket: (< is write to socket , > is readed from socket, numbers in :99: are the message-length)
>>> import bjsonrpc
>>> c = bjsonrpc.connect()
>>> r = c.call.echo("hello world")
>>> c._debug_socket=True # enable debugging output.
>>> r = c.call.echo("hello world")
<:49: {"params":["hello world"],"method":"echo","id":2}
>:44: {"id":2,"result":"hello world","error":null}
>>> l1 = c.call.mewList() # syntax error: **m**ew instead of new
<:27: {"method":"mewList","id":3}
>:73: {"id":3,"result":null,"error":"ValueError(\\"Unkown method 'mewList'\\",)"}
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "../bjsonrpc/proxies.py", line 47, in fn
return self._conn._proxy(self.sync_type, name, args, kwargs)
File "../bjsonrpc/connection.py", line 263, in _proxy
return req.value
File "../bjsonrpc/request.py", line 79, in value
raise ServerError(self.response['error'])
ServerError: ValueError("Unkown method 'mewList'",)
>>> l1 = c.call.newList() # this returns a remote object.
<:27: {"method":"newList","id":4}
>:65: {"id":4,"result":{"__remoteobject__":"mylist_0001"},"error":null}
>>> l1.call.add(1) # the remote object has its own methods.
<:48: {"params":[1],"method":"mylist_0001.add","id":5}
>:35: {"id":5,"result":null,"error":null}
>>> l1.call.items()
<:37: {"method":"mylist_0001.items","id":6}
>:34: {"id":6,"result":[1],"error":null}
[1]
>>> del l1 # throw away the object in the remote server.
<:42: {"method":"mylist_0001.__delete__","id":7}
>:35: {"id":7,"result":null,"error":null}
You can run a standard benchmark using the example1 client and server. In my home computer (which is 5 years old) it gives the following results:
- Notify Total: 2.08s 4814.06 req/s
- Method Total: 1.28s 2347.58 req/s
- Call Total: 0.32s 1583.29 req/s
The computer at my office (Core 2 Duo) gives about 20K req/s on Notify,10K on Method, 5K on Call.
example1b-client is a specific example for PythonCE for PDA's with Windows Mobile. The numbers are about 120,60,50 req/s.
Over a real network, of course, the numbers are lower because of the latency and bandwidth limitations:
- Notify and Method are asynchronous calls, so they are bandwith-bounded. Notify should be the twice as faster as Method because it requires no response from server. Expect about 60bytes per call, so in a Internet connection with 300kbit uplink you will be able to handle about 625 requests per second.
- Call is a syncronous call, so is latency-bounded. In a connection with 80ms latency, a syncronous call would take 160ms, so it's possible to serialize about 375 calls in a minute.