09.11.2016 Views

Foundations of Python Network Programming 978-1-4302-3004-5

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

CHAPTER 18 ■ RPC<br />

dispatcher = lovely.jsonrpc.dispatcher.JSONRPCDispatcher()<br />

dispatcher.register_method(lengths)<br />

app = lovely.jsonrpc.wsgi.WSGIJSONRPCApplication({'': dispatcher})<br />

server = make_server('localhost', 7002, app)<br />

print "Starting server"<br />

while True:<br />

» server.handle_request()<br />

You can see that the Lovely Systems package — which was written recently using modern <strong>Python</strong><br />

technology — <strong>of</strong>fers a WSGI wrapper around its JSON-RPC dispatcher, making it easy to incorporate into<br />

modern <strong>Python</strong> web application stacks, or to deploy stand-alone using the Standard Library’s wsgiref<br />

package.<br />

The server code is quite simple, as an RPC mechanism should be. As with XML-RPC, we merely need<br />

to name the functions that we want <strong>of</strong>fered over the network, and they become available for queries.<br />

(You can also pass an object, and its methods will be registered with the server all at once.)<br />

Listing 18–6. JSON-RPC Client<br />

#!/usr/bin/env python<br />

# <strong>Foundations</strong> <strong>of</strong> <strong>Python</strong> <strong>Network</strong> <strong>Programming</strong> - Chapter 18 - jsonrpc_client.py<br />

# JSON-RPC client<br />

from lovely.jsonrpc import proxy<br />

proxy = proxy.ServerProxy('http://localhost:7002')<br />

print proxy.lengths((1,2,3), 27, {'Sirius': -1.46, 'Rigel': 0.12})<br />

Writing client code is also quite simple. Sending several objects whose lengths we want measured —<br />

and having those data structures sent right back by the server — enables us to see several details about<br />

this particular protocol.<br />

First, note that the protocol allowed us to send as many arguments as we wanted; it was not<br />

bothered by the fact that it could not introspect a static method signature from our function. This is<br />

similar to XML-RPC, but it is very different from XML-RPC mechanisms built for traditional, staticallytyped<br />

languages.<br />

Second, note that the None value in the server’s reply passes back to us unhindered. This is because<br />

this value is supported natively by the protocol itself, without our having to activate any non-standard<br />

extensions:<br />

$ python jsonrpc_server.py<br />

Starting server<br />

[In another command window:]<br />

$ python jsonrpc_client.py<br />

[[3, [1, 2, 3]], [None, 27], [2, {'Rigel': 0.12, 'Sirius': -1.46}]]<br />

Third, note that there is only one kind <strong>of</strong> sequence supported by JSON-RPC, which means that the<br />

tuple sent by our client had to be coerced to a list to make it across.<br />

Of course, the biggest difference between JSON-RPC and XML-RPC — that the data payload in this<br />

case is a small, sleek JSON message that knows natively how to represent each <strong>of</strong> our data types — is not<br />

even visible here. This is because both mechanisms do such a good job <strong>of</strong> hiding the network from our<br />

code. Running Wireshark on my localhost interface while running this example client and server, I can<br />

see that the actual messages being passed are as follows:<br />

{"version": "1.1",<br />

"params": [[1, 2, 3], 27, {"Rigel": 0.12, "Sirius": -1.46}],<br />

"method": "lengths"}<br />

{"result": [[3, [1, 2, 3]], [null, 27],<br />

[2, {"Rigel": 0.12, "Sirius": -1.46}]]}<br />

314

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!