xmlrpc学习笔记(c++示例代码)

xmlrpc是一种通过网络进行过程调用的快速并且简单的方法。xmlrpc将过程调用需要的参数转换成xml文档,并以http协议发送给远端服务器,服务器将以xml协议将结果回复给客户端。以下是在使用xmlrpc时需要用到的参考资料。


介绍了什么是xmlrpc, 介绍了C/C++应用程序使用xmlrpc时需要用到的lib文件以及每个lib文件大概的作用,手册里面还有C和C++实现的xmlrpc客户端和服务器示例代码。

General Library Information - C: http://xmlrpc-c.sourceforge.net/doc/libgeneral.html
介绍了xmlrpc-c的C编程库

general library information - C++: http://xmlrpc-c.sourceforge.net/doc/libgeneral++.html
介绍了xmlrpc-c的C++编程库

详细讲解了libxmlrpc库
详细讲解了libxmlrpc++库

--------------------------------------------------------------------------------------------------------------------

以下过程基于windows平台

一. 下载xmlrpc-c源码

下载地址如上。在下载的工程文件中找到目录Windows,进入目录并查看ReadMeWin32.txt文件,提示要你运行ConfigureWin32.bat批处理文件(这个批处理文件就是用来生成一些.h头文件,这些头文件提供了一些宏定义,在windows平台中编译生成xmlrpc相关库的时候需要使用),双击运行就好。用vs打开工程(Windows->project),可以发现所有的xmlrpc库都是动态库,编译并生成相关的库。在编译过程中可能会出现一些错误,基本上都是小错误,很容易定位并解决。

二. 编写测试代码

在测试代码中,链接到项目中的lib文件只需要两个(libxmlrpc++.lib libxmlrpc_util++.lib)。

可能需要的基础知识:

2.1 在xmlrpc中,所有的接口使用的是特殊数据类型,如value_int,、value_i8等。所有的这些

数据类型都继承自一个名叫value的类,value可以表示任何派生类对象(你可以将任何派生类

对象赋值给value对象)。xmlrpc数据类型与C/C++数据类型之间的转换只需要调用一个名为

cvalue的成员函数,使用时需要注意value并不是一个抽象类型,value中的cvalue不是虚函数,

每个派生类各自实现了cvalue函数。当你得到一个value对象的时候,你就需要判断他是什么数据类型,

这时候需要使用value的另外一个成员函数type。type只存在与value类中,使用type能够得到该value具体

表示的对象的类型是什么,它返回的是type_t对象。type_t对象是枚举类型,定义了所有数据类型。

2.2 xmlrpc内部使用智能指针管理对象,为实现智能管理,xmlrpc中的类都继承自girmem::autoObject

对于从girmem::autoObject派生的每个类,都有一个派生自autoObjectPtr的类,名字相差一个后缀Ptr。

在xmlrpc中想要使用autoObject对象时,使用的是对应的autoObjectPtr对象,因为autoObject构造函数是

私有的,内部使用std::auto_ptr,它声明了autoObjectPtr类为友元类。

2.3 所有接口调用中如果出现错误就会跑出一个xmlrpc特有的girerr::error对象,error继承自std::exception。

2.4 使用xmlrpc可以很方便的进行Base64编码和解码,只需要使用两个接口base64FromBytesbytesFromBase64

2.5 xmlrpc客户端可以同步请求服务器,也可以异步请求服务器,但貌似异步请求没有在libxmlrpc++库中实现,要想使用异步请求,只能写C代码了。

以下示例代码是从上面贴出的文档中找到的,做了些许修改,仅为测试而用。

我定义了两个宏XMLRPC_CPP、XMLRPC_C,目的是方便编译C++或者C的代码。

目前只做了对C++的测试,所以只编译了C++部分代码,亲测可用,

至于C的用到再说吧。

客户端代码:

#include "stdafx.h"
#include <string>
#include <iostream>
#define XMLRPC_CPP 1
#define XMLRPC_C 0

#if XMLRPC_CPP

#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/client_simple.hpp>

#elif XMLRPC_C



#endif

using namespace std;
using namespace xmlrpc_c;

int _tmain(int argc, _TCHAR* argv[])
{
#if XMLRPC_CPP
	string const serverUrl("http://10.10.30.166:8088/RPC2");
	string const methodName("sample.add");
	//string const methodName("SuspectPersonManage");
	xmlrpc_c::clientSimple myClient;
	xmlrpc_c::value result;
	xmlrpc_c::paramList paramLst;
	xmlrpc_c::cstruct paramIn;
	paramIn["first"] = xmlrpc_c::value_int(1);
	paramIn["second"] = xmlrpc_c::value_int(2);
	paramLst.addc(paramIn);
	//myClient.call(serverUrl, methodName, "ii", &result, 5, 7);
	myClient.call(serverUrl, methodName, paramLst, &result);

	int const sum((xmlrpc_c::value_int(result)));
	// Assume the method returned an integer; throws error if not

	cout << "Result of RPC (sum of 5 and 7): " << sum << endl;

	//string strXmlRpcSrvUrl("http://10.10.30.166:9090/RPC2");
	//xmlrpc_c::clientSimple myClient;
	//xmlrpc_c::value result;
	//xmlrpc_c::paramList paramLst;
	//xmlrpc_c::cstruct struct_param;
	//xmlrpc_c::carray image_array_param;
	//xmlrpc_c::carray imagetype_array_param;

	//struct_param["CommandType"] = value_int(0);
	//struct_param["Name"] = value_string("luffy");
	//struct_param["Sex"] = value_int(1);
	//struct_param["IdNumber"] = value_string("123456789");
	//struct_param["Phone"] = value_string("");
	//struct_param["Address"] = value_string("");
	//struct_param["person_type"] = value_string("1");
	//image_array_param.push_back(value_string("abcdefg"));
	//imagetype_array_param.push_back(value_int(0));
	//struct_param["Image"] = value_array(image_array_param);
	//struct_param["ImageType"] = value_array(imagetype_array_param);

	//paramLst.addc(struct_param);

	//myClient.call(strXmlRpcSrvUrl, "SuspectPersonManage", paramLst, &result);

#elif XMLRPC_C
	xmlrpc_env env;
	xmlrpc_value * resultP;
	int sum;
	char * const clientName = "XML-RPC C Test Client";
	char * const clientVersion = "1.0";
	char * const url = "http://localhost:8080/RPC2";
	char * const methodName = "sample.add";

	/* Initialize our error-handling environment. */
	xmlrpc_env_init(&env);

	/* Start up our XML-RPC client library. */
	xmlrpc_client_init2(&env, XMLRPC_CLIENT_NO_FLAGS, clientName, clientVersion, NULL, 0);
	[handle possible failure of above]

	/* Make the remote procedure call */
	resultP = xmlrpc_client_call(&env, url, methodName,
		"(ii)", (xmlrpc_int32)5, (xmlrpc_int32)7);
	[handle possible failure of above]

	/* Print out the sum the server returned */
	xmlrpc_parse_value(&env, resultP, "i", &sum);
	[handle possible failure of above]

	printf("The sum  is %d\n", sum);

	/* Dispose of our result value. */
	xmlrpc_DECREF(resultP);

	/* Clean up our error-handling environment. */
	xmlrpc_env_clean(&env);

	/* Shutdown our XML-RPC client library. */
	xmlrpc_client_cleanup();
#endif

	return 0;
}

服务端代码:

#include "stdafx.h"
#include <assert.h>
#define XMLRPC_CPP 1
#define XMLRPC_C 0

#if XMLRPC_CPP

#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
#include <xmlrpc-c/server_abyss.hpp>

#elif XMLRPC_C

#include <xmlrpc.h>
#include <xmlrpc_server.h>
#include <xmlrpc_server_abyss.h>

#endif


#if XMLRPC_CPP

class sampleAddMethod : public xmlrpc_c::method {
public:
	sampleAddMethod() {}

	void
		execute(xmlrpc_c::paramList const& paramList,
		xmlrpc_c::value *   const  retvalP) {
//			xmlrpc_c::cstruct tmp  = paramList.getStruct(0);

// 			int const addend(paramList.getInt(0));
// 			int const adder(paramList.getInt(1));
//			paramList.verifyEnd(2);

			xmlrpc_c::cstruct struct_param = paramList.getStruct(0);
			assert(struct_param["first"].type() == xmlrpc_c::value::TYPE_INT);
			assert(struct_param["second"].type() == xmlrpc_c::value::TYPE_INT);
			xmlrpc_c::value_int value1 = struct_param["first"];
			xmlrpc_c::value_int value2 = struct_param["second"];

			int const addend =  value1.cvalue();
			int const adder = value2.cvalue();

			paramList.verifyEnd(1);	//检测参数个数,如果位置1不是结尾标志(类似eof),那么抛出异常。

			*retvalP = xmlrpc_c::value_int(addend + adder);
	}
};

#elif XMLRPC_C

static xmlrpc_value * sample_add(xmlrpc_env*   const envP,
								 xmlrpc_value* const paramArrayP,
								 void* const serverContext)
{

	xmlrpc_int32 x, y, z;

	/* Parse our argument array. */
	xmlrpc_parse_value(envP, paramArrayP, "(ii)", &x, &y);
	if (envP->fault_occurred)
		return NULL;

	/* Add our two numbers. */
	z = x + y;

	/* Return our result. */
	return xmlrpc_build_value(envP, "i", z);
}

#endif


int _tmain(int argc, _TCHAR* argv[])
{
#if XMLRPC_CPP
	xmlrpc_c::registry myRegistry;

	xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);

	myRegistry.addMethod("sample.add", sampleAddMethodP);

	xmlrpc_c::serverAbyss myAbyssServer(
		myRegistry,
		8088,              // TCP port on which to listen
		"/tmp/xmlrpc_log"  // Log file
		);

	myAbyssServer.run();
	// xmlrpc_c::serverAbyss.run() never returns
	assert(false);
#elif XMLRPC_C
	xmlrpc_server_abyss_parms serverparm;
	xmlrpc_registry * registryP;
	xmlrpc_env env;

	xmlrpc_env_init(&env);

	registryP = xmlrpc_registry_new(&env);

	xmlrpc_registry_add_method(
		&env, registryP, NULL, "sample.add", &sample_add, NULL);

	serverparm.config_file_name = argv[1];
	serverparm.registryP = registryP;

	printf("Starting XML-RPC server...\n");

	xmlrpc_server_abyss(&env, &serverparm, XMLRPC_APSIZE(registryP));

#endif

	return 0;
}

运行结果:



服务器会报出这种错误,因为这个日志文件确实没有,我也没深究,不影响使用就行。

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
XML-RPC 是一种远程过程调用协议,可以使用 XML-RPC 库在 C++ 中实现远程过程调用。以下是一个简单的示例代码,演示如何在 C++ 中使用 XML-RPC。 ```c++ #include <xmlrpc-c/base.hpp> #include <xmlrpc-c/client_simple.hpp> #include <iostream> #include <string> using namespace std; using namespace xmlrpc_c; int main(int argc, char *argv[]) { // 创建 XML-RPC 客户端对象 clientSimple myClient; // 设置 XML-RPC 服务器地址和端口号 string const serverUrl("http://localhost:8080/RPC2"); string const methodName("sample.add"); int const arg1(4); int const arg2(5); // 创建参数列表 paramList myParams; myParams.add(param::value(arg1)); myParams.add(param::value(arg2)); // 调用远程过程并获取返回值 value const result(myClient.call(serverUrl, methodName, myParams)); int const sum(result.getInt()); // 输出结果 cout << "The sum of " << arg1 << " and " << arg2 << " is " << sum << endl; return 0; } ``` 在上面的示例中,我们首先创建了一个 `clientSimple` 对象,它是 XML-RPC 客户端的一个简单实现。接下来,我们设置了 XML-RPC 服务器的地址和端口号,并定义了要调用的远程方法的名称以及传递给该方法的参数。然后,我们将参数添加到参数列表中,调用远程方法,并获取返回值。最后,我们将返回值转换为整数并输出结果。 需要注意的是,在使用 XML-RPC 时,服务器端也必须支持 XML-RPC 协议。您需要在服务器端实现 XML-RPC 服务器并公开需要调用的远程方法。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值