You can make your XML-RPC server accept multiple calls simultaneously. This means that multiple function calls can return a single result. In addition to this, if your server is multithreaded, then you can execute more code after the server is launched in a single thread. The program's main thread will not be blocked in this manner.
We can create a ServerThread
class inheriting from the threading.Thread
class and wrap a SimpleXMLRPCServer
instance in an attribute of this class. This can be set up to accept multiple calls.
Then, we can create two functions: one launches the multithreaded, multicall XML-RPC server and the other creates a client to that server.
Listing 8.2 gives the code for writing a multithreaded, multicall XML-RPC server, as shown:
#!/usr/bin/env python # Python Network Programming Cookbook -- Chapter – 8 # This program is optimized for Python 2.7. # It may run on any other version with/without modifications. import argparse import xmlrpclib import threading from SimpleXMLRPCServer import SimpleXMLRPCServer # some trivial functions def add(x,y): return x+y def subtract(x, y): return x-y def multiply(x, y): return x*y def divide(x, y): return x/y class ServerThread(threading.Thread): def __init__(self, server_addr): threading.Thread.__init__(self) self.server = SimpleXMLRPCServer(server_addr) self.server.register_multicall_functions() self.server.register_function(add, 'add') self.server.register_function(subtract, 'subtract') self.server.register_function(multiply, 'multiply') self.server.register_function(divide, 'divide') def run(self): self.server.serve_forever() def run_server(host, port): # server code server_addr = (host, port) server = ServerThread(server_addr) server.start() # The server is now running print "Server thread started. Testing the server..." def run_client(host, port): # client code proxy = xmlrpclib.ServerProxy("http://%s:%s/" %(host, port)) multicall = xmlrpclib.MultiCall(proxy) multicall.add(7,3) multicall.subtract(7,3) multicall.multiply(7,3) multicall.divide(7,3) result = multicall() print "7+3=%d, 7-3=%d, 7*3=%d, 7/3=%d" % tuple(result) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Multithreaded multicall XMLRPC Server/Proxy') parser.add_argument('--host', action="store", dest="host", default='localhost') parser.add_argument('--port', action="store", dest="port", default=8000, type=int) # parse arguments given_args = parser.parse_args() host, port = given_args.host, given_args.port run_server(host, port) run_client(host, port)
If you run this script, you will see the output similar to the following:
$ python 8_2_multithreaded_multicall_xmlrpc_server.py --port=8000 Server thread started. Testing the server... localhost - - [25/Sep/2013 17:38:32] "POST / HTTP/1.1" 200 - 7+3=10, 7-3=4, 7*3=21, 7/3=2
In this recipe, we have created a ServerThread
subclass inheriting from the Python threading library's Thread
class. This subclass initializes a server attribute that creates an instance of the SimpleXMLRPC
server. The XML-RPC server address can be given via the command-line input. In order to enable the multicall function, we called the register_multicall_functions()
method on the server instance.
Then, four trivial functions are registered with this XML-RPC server: add()
, subtract()
, multiply()
, and divide()
. These functions do exactly the same operation as their names suggest.
In order to launch the server, we pass a host and port to the run_server()
function. A server instance is created using the ServerThread
class discussed earlier. The start()
method of this server instance launches the XML-RPC server.
On the client side, the run_client()
function accepts the same host and port arguments from the command line. It then creates a proxy instance of the XML-RPC server discussed earlier by calling the ServerProxy()
class from xmlrpclib
. This proxy instance is then passed onto the MultiCall
class instance, multicall
. Now, the preceding four trivial RPC methods can be run, for example, add
, subtract
, multiply
, and divide
. Finally, we can get the result via a single call, for example, multicall()
. The result tuple is then printed in a single line.
3.128.198.59