 | Level: Intermediate Karthik Subbian (ksubbian@in.ibm.com), Staff Software Engineer, IBM India Ramakrishnan Kannan (rkrishnan@in.ibm.com), Staff Software Engineer, IBM India
20 Jun 2006 XML-RPC is a lightweight, simple and powerful messaging protocol that enables complex XML-based communication across disparate platforms. In this article you'll see how to build your own XML-RPC-based service for C++ programs.
Introduction
Today the growing popularity of the Internet and its inherent advantages have motivated developers and IT departments to migrate complex C/C++ business and scientific applications to a Web-based environment. Web services such as Simple Object Access Protocol (SOAP), Representational State Transfer (REST), and XML remote procedure protocol (XML-RPC) facilitate integration of such legacy applications to the World Wide Web, including XML-RPC as a mechanism to integrate existing C/C++ programs with other client-side technologies. This article will help you determine when to choose XML-RPC versus SOAP and REST. Also, a step-by-step guide and sample code snippets for C++ integration using an open source XML-RPC Library is provided.
Why XML-RPC?
The challenge of integrating C/C++ code has been solved in many ways. Some of the classical approaches of C/C++ code integration are through Common Object Request Broker Architecture (CORBA), distributed component object model (DCOM), remote method invocation (RMI)
Internet Inter-ORB Protocol (IIOP) and Java™ native interface (JNI) interfaces.
Figure 1 illustrates three different applications developed in three different programming languages (Java, VC++, PL/1) integrating with existing C++ code using the classical approaches mentioned above.
Figure 1. Current scenario without XML-RPC
As you can see, C++ code should expose the respective interfaces for each of the RMI/IIOP/JNI, CORBA and DCOM client-side integration technologies. This requires three-times the development effort and clearly makes the process of deploying and managing such complex interfaces much more difficult and cumbersome.
XML-RPC is a better choice in these situations because the development, deployment and management becomes easy.
Figure 2. With XML-RPC
Figure 2 illustrates invoking a C++ program through a remote procedure call using XML over HTTP. Alternate technologies like SOAP and REST, can serve the same purpose. Yet as you'll see in the next section, there are some key differences between these technologies.
Comparison of SOAP, XML-RPC and REST
Even through all three protocols support XML-RPC over HTTP there are differences among them with respect to C++. Table 1 offers a detailed comparison of the elements of these protocols.
Table 1. Comparison of SOAP, XML-RPC and REST
| SOAP | XML-RPC | REST |
|---|
| Definition | SOAP is a lightweight protocol for information exchange in a decentralized, distributed environment. It is an XML-based protocol that consists of three parts: an envelope, a set of encoding rules, and a convention for representing remote procedure calls and responses. | This is a remote procedure call that uses HTTP as the transport and XML as the encoding. XML-RPC is designed to be as simple as possible, while allowing complex data structures to be transmitted, processed and returned. | Representational State Transfer is intended to evoke an image of how a well-designed Web application behaves: a network of Web pages,
where the user progresses through an application by selecting links, resulting in the
next page being transferred to the user and rendered for their use. | | Goals | SOAP extends XML-RPC by implementing user defined data types, the ability to specify the recipient, message specific processing control, and other features. | A clean, extensible format that's very simple. An HTML coder tshould be able to look at a file containing an XML-RPC procedure call, understand what it's doing, and be able to modify it and have it work on the first or second try. An easy-to-implement protocol that could quickly be adapted to run in other environments or on other operating systems. | REST was created to provide a design pattern for how the Web should work, and to serve as the guiding framework for the Web standards and designing Web services. | | Data types supported | Integer, Boolean, ASCII String, double precision signed floating point number, date-time, structs, arrays, array of bytes, enumeration,
User-defined data types, polymorphic accessors | Integer, boolean, ASCII string, double-precision signed floating point number, date-time, structs, arrays. | Implementation specific. In general supported types are Integer, boolean, ASCII string, double-precision signed floating point number, date-time, set, list, properties. | | Simplicity | Slightly complex compared to XML-RPC | Easy to understand and develop | Implementation-specific | | Stability | Accepted standard under W3C | Not a standard | Architecture reference. Standard not needed | | Interoperability | Cannot interoperate with REST/XML-RPC | Cannot interoperate with REST/SOAP | Cannot interoperate with SOAP/XML-RPC | | Tooling | Many major companies including IBM and Microsoft started supporting SOAP in their tools. | Tooling is still evolving. | Not many tooling support is available. | | Customizability | Highly customizable, data-types and protocol independent | Lightweight, can work only on HTTP, limited data type support | Works only on HTTP | | Library | Many open source libraries are available. | Many open source libraries are available. The following sections offer descriptions | Not many implementation library available |
Table 2. Various XML-RPC implementations for C++
| Library and package name | Description |
|---|
| PDEL | Packet Design Embedded Library is a C library containing XML-RPC implementation of client and server through http_xml_send_xmlrpc and http_servlet_xmlrpc methods. These functions help you to send your custom xml data over the http transport protocol. This package also has many other features other than XML-RPC. | | XMLRPC++ | This is a C++ implementation of the XML-RPC standard. It comes with a simple server and a client. Using object-oriented techniques, we can inherit these server and client classes and implement our own XML-RPC server exposing our business functions as services. In this article, we have used this library for sample implementation and examples. | | XMLRPC-C | This is a C implementation which can be used by both C and C++ applications for exposing there methods as services. This package includes an abyss web server. For exposing C++ methods we could write C style wrapper to the required C++ method, and expose this method using this library. |
Install XML-RPC++ library
The first step towards enabling your C++ program for XML-RPC is to download and install an XML-RPC library implementation. Various implementations are available for C++ programs. A link to more implementations can be found in the Resources section.
Our sample programs use the XMPLRPC++ implementation. The details of downloading and installing this to Linux, AIX, 32-Bit windows platforms, and other familiar platforms, can be found in the Resources section. Our sample implementation is on the Red Hat 9 platform, using XML-RPC++ 0.7 library.
A sample C++ application
The sample application here is a simple addition operation on two integers, using a user-defined class called " operations " . Listing 1 shows the code snippet for the operations class.
Listing 1. Operations
class operations {
public:
int add();
operations(int i, int j);
private:
int op1;//Operand 1
int op2;//Operand 2
};
|
The constructor for this class takes two integer parameters and sets them to op1 and op2 private variables respectively. The add method for this class is shown in Listing 2. This is the method, we are interested to expose as a XML-RPC service.
Listing 2. Operations.cpp
int operations::add()
{
std::cout << "Sum of "<<op1<<" + "<<op2<<" = "<<op1+op2<<std::endl;
return(op1 + op2);
}
|
Components of XML-RPC library
In this section we use a a class diagram to explain various components of the XML-RPC library and how it interfaces with our operations class for the server side.
Figure 3. Class diagram for XML-RPC library and sample application
Each class is explained in detail in Table 3.
Table 3. Class details
| Class name | Purpose |
|---|
| Operations | Add method to be exposed is implemented in this class | | Add | Wrapper class which will call the operations add method(). This class also inherits from myXmlRpcServerMethod | | myXmlRpcServerMethod | This class inherits from XML-RPC Library XmlRpcServerMethod class. The execute of this is overridden in Add class, through inheritance. | | xmlRpcServermethod | Every method that needs to be registered to the server has to inherit from this class through myXmlRpcServerMethod class and implement its execute method. This execute method will be the wrapper for the actual service exposed. Whenever an XML-RPC call is received by the server, it immediately triggers the execute method of this wrapper class. In our case, Add will be the wrapper class and its execute method will be called when we invoke "Add" service from client side. | | myXmlRpcServer | This class has two important private variables
- pm_serverMethods: List of pointers to myXmlRpcServerMethods which are registered in server.
- pm_xmlRpcServer: To set the server IP, Port and other properties.
Three important methods
- Class constructor: initializes server object with ip/port details and binds it.
- pm_registerMethods: create a pointer object to Add class and push it to the list, pm_serverMethods.
- run: This is a wrapper for work method in xmlRpcServer class
| | xmlRpcServer | This class is the XML-RPC server class which creates a server object. This class has following two important methods
- bindAndListen(port): bind and listen to the specific port mentioned
- work(...): start the server
|
Listing 3 shows the code for each .cpp file for each class in the above table. Since xmlRpcServer and xmlRpcServerMethod are implemented in the XML-RPC library, we concentrate on the remaining four classes.
Listing 3. myXmlRpcServer.cpp
#include "myXmlRpcServer.h"
using namespace XmlRpc;
using namespace std;
myXmlRpcServer::myXmlRpcServer()
{
//call register methods
pm_registerMethods();
//set port bind and listen
int port = 8085;
pm_xmlRpcServer.bindAndListen(port);
std::cout<<"XmlRpcSever running in port "<<port<<std::endl;
}
void
myXmlRpcServer::pm_registerMethods()
{
Add* a=new Add(&pm_xmlRpcServer);
myXmlRpcServerMethod *p=a;
pm_serverMethods.push_back(p);
}
void
myXmlRpcServer::run()
{
pm_xmlRpcServer.work(-1);
}
|
Listing 4. myXmlRpcServer.h
#include <iostream>
#include "myXmlRpcServerMethods.h"
#include "XmlRpc.h"
class myXmlRpcServer {
public:
myXmlRpcServer();
void run();
private:
void pm_registerMethods();
XmlRpc::XmlRpcServer pm_xmlRpcServer;
std::list< myXmlRpcServerMethod* > pm_serverMethods;
};
|
Listing 5 and Listing 6 show code for classes that are used for registering the methods to the XmlRpc Server that comes as a part of the XML-RPC library.
Listing 5. myXmlRpcServerMethods.cpp
#include <iostream>
#include "myXmlRpcServer.h"
#include "operations.h"
using namespace std;
Add::Add(XmlRpcServer* s) : myXmlRpcServerMethod("Add", s) {};
Void Add::execute(XmlRpcValue & params, XmlRpcValue& result)
{
operations a(10,12);
try
{
cout << "Inside Add::execute method\n";
result = a.add();
}
catch(std::exception & stde)
{
throw XmlRpcException(stde.what());
}
}
|
Listing 6. myXmlRpcServerMethods.h
class myXmlRpcServerMethod : public XmlRpcServerMethod
{
public:
myXmlRpcServerMethod
(const char *name, XmlRpcServer * server):XmlRpcServerMethod(name, server) {}
virtual void execute(XmlRpcValue & params, XmlRpcValue& result) {assert(0);}
};
class Add:public myXmlRpcServerMethod
{
public:
Add(XmlRpcServer* s);
virtual void execute(XmlRpcValue & params, XmlRpcValue& result);
};
|
Server driver
The entry point for the server side will be through the server driver program. It is the place to instantiate myXmlRpcServer object and call the run() method, which will eventually start the server.
Listing 7. myServerDriver.cpp
#include <iostream>
#include "myXmlRpcServer.h"
int main(int argc, char* argv[])
{
myXmlRpcServer GeeBoomBaa;
std::cout<<"About to run the server\n";
GeeBoomBaa.run();
return 0;
}
|
Starting the server
In order to compile the code, remember to include the (XML_RPC_INSTALL_DIR)/src and (XML_RPC_INSTALL_DIR)/include directory. For linking purposes, include the libXmlRpc.a library. Once the code is successfully compiled and linked, you will have an executable, which is the XML-RPC Server. In our sample implementation, the server will run on localhost and listen to port 8085. This is hard-coded in myXmlRpcServer.cpp file. Instead, it could read a configuration file or you could pass this as a parameter from the command prompt. Start the server by running the a.out program obtained after successful compilation and linking.
Sample client
Sample client should instantiate an object from XmlRpcClient class provided in the XML-RPC library. The "execute(...)" method of this class, actually takes three parameters:
- method name as const char*
- port number as const int
- An optional uri string to be sent as Uri in the http get header
Listing 8 shows a sample client, which will execute the "add(...)" method and print the result on the client side.
Listing 8. sampleClient.cpp
#include <iostream>
#include "XmlRpc.h"
using namespace XmlRpc;
int main(int argc, char* argv[])
{
const char *server = "localhost";
const int port = 8085;
const char *uri = NULL;
XmlRpcValue args, res;
XmlRpcClient c( server, port, uri);
c.execute("Add", args, res);
std::cout<<"result is "<<res<<std::endl;
}
|
Conclusion
XML-RPC is a lightweight, simple and powerful messaging protocol that enables complex XML-based communication across disparate platforms. The inherent simplicity of this standard is very powerful and useful for integrating legacy applications with an enterprise. The open source nature of various XML-RPC implementations has promoted this technology to gain more popularity among Enterprise Application Integrations. With the advent of more and more sophisticated tools for XML-RPC, we expect this technology to become a "defacto" standard for intra-enterprise integration.
Resources Learn
Get products and technologies
Discuss
About the authors  | 
|  | Karthik Subbian is currently building optimization products for manufacturing enterprises in IBM India Software Laboratory, Bangalore. He also has experience helping clients imanage their applications and migrate them to IBM platforms. His areas of interests in the software arena include Grid computing, XML, Web services and SOA. He has co-authored IBM Redbooks on Grid computing technology. He is an IBM Certified XML Solution Developer and Sun Certified Java Programmer. |
 | 
|  | Ramakrishnan Kannan works on host integration in IBM India Software Laboratory in Bangalore. He has been a developer for IBM personal communications and communication servers products. In addition to his development work, he works with customers in IBM Asia-Pacific region for Web service enablement of Host Applications. He has conducted webservices awareness session to business partners such as Infosys for Developerworks. He is an IBM Certified XML Solution Developer and Sun Certified Java Professional. His interests are host integration, distributed computing, SOA, and networking. |
Rate this page
|  |