TwistedNetstring

JSON-RPC over TCP

Dependencies

  • Twisted
  • simplejson

Notes

This version was built from the adytum.twisted.web2.jsonrpc code by essentially replacing the HTTP-related code with twisted.protocols.basic.NetstringReceiver code.

One of the benefits of using Netstrings for this are string-length checks. There is a default maximum length that can be sent to the server. If you are sending large JSON strings to the server, you may need to override the default (1024 bytes).

The tests for adytum.twisted.web2.jsonrpc were also included/adapted and pass successfully.

Import

>>> from txjsonrpc.netstring import jsonrpc

Usage

Server

The server setup is a little different than with the HTTP versions. In particular, the manner of setting up subhandlers has changed. But first, let's look at a server example:

from twisted.application import service, internet

from txjsonrpc.netstring import jsonrpc

class Example(jsonrpc.JSONRPC):
    """An example object to be published."""

    def jsonrpc_echo(self, x):
        """Return all passed args."""
        return x

class Testing(jsonrpc.JSONRPC):

    def jsonrpc_getList(self):
        """Return a list."""
        return [1,2,3,4,'a','b','c','d']

class Math(jsonrpc.JSONRPC):

    def jsonrpc_add(self, a, b):
        """Return sum of arguments."""
        return a + b

# Setup the subhandlers for our RPC API
factory = jsonrpc.RPCFactory(Example)
factory.putSubHandler('math', Math)
factory.putSubHandler('testing', Testing)

# Let's add introspection, just for fun
factory.addIntrospection()

application = service.Application("Example JSON-RPC Server")
jsonrpcServer = internet.TCPServer(7080, factory)
jsonrpcServer.setServiceParent(application)

With the HTTP versions, you create instances of your JSONRPC subclasses when adding them as subhandlers:

top = Example()
top.addSubHandler('math', Math())
top.addSubHandler('testing', Testing())

But for the TCP version, you can see that we add the JSONRPC _subclasses_ to the *factory* instead:

factory = jsonrpc.RPCFactory(Example)
factory.putSubHandler('math', Math)
factory.putSubHandler('testing', Testing)

As for adding the introspection, there are two ways to do it with the TCP version. One way is how we did it in the example server above. The other way is similar to the HTTP RPC servers:

addIntrospection(factory)

But note that you are passing the _factory_ and not the parent instance.

Save the server code from above as server_subhandled.tac and run with the following command:

$ twistd -noy server_subhandled.tac

Client

Here is example client code for the server above:

from twisted.internet import reactor
from twisted.internet import defer

from txjsonrpc.netstring.jsonrpc import Proxy

def printValue(value):
    print "Result: %s" % str(value)

def printError(error):
    print 'error', error

def shutDown(data):
    print "Shutting down reactor..."
    reactor.stop()

print "Making remote calls..."
proxy = Proxy('127.0.0.1', 7080)
dl = []

d = proxy.callRemote('system.listMethods')
d.addCallbacks(printValue, printError)
dl.append(d)

d = proxy.callRemote('echo', 'bite me')
d.addCallbacks(printValue, printError)
dl.append(d)

d = proxy.callRemote('testing.getList')
d.addCallbacks(printValue, printError)
dl.append(d)

d = proxy.callRemote('math.add', 3, 5)
d.addCallbacks(printValue, printError)
dl.append(d)

dl = defer.DeferredList(dl)
dl.addCallback(shutDown)
reactor.run()

Save this file as client_subhandled.py and run it from the command line. You should see output something like this:

Making remote calls...
Result: [u'echo', u'math.add', u'system.listMethods', u'system.methodHelp', u'system.methodSignature', u'testing.getList']
Result: [1, 2, 3, 4, u'a', u'b', u'c', u'd']
Result: 8
Result: bite me
Shutting down reactor...

txJSON-RPC/TwistedNetstring (last edited 2008-08-06 16:59:59 by localhost)