--------------------------------------------------------------------------------------------------------------------
以下过程基于windows平台
下载地址如上。在下载的工程文件中找到目录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编码和解码,只需要使用两个接口base64FromBytes,bytesFromBase64。
2.5 xmlrpc客户端可以同步请求服务器,也可以异步请求服务器,但貌似异步请求没有在libxmlrpc++库中实现,要想使用异步请求,只能写C代码了。
以下示例代码是从上面贴出的文档中找到的,做了些许修改,仅为测试而用。
我定义了两个宏XMLRPC_CPP、XMLRPC_C,目的是方便编译C++或者C的代码。
目前只做了对C++的测试,所以只编译了C++部分代码,亲测可用,
至于C的用到再说吧。
客户端代码:
#include "stdafx.h"
#include
#include
#define XMLRPC_CPP 1
#define XMLRPC_C 0
#if XMLRPC_CPP
#include
#include
#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
#define XMLRPC_CPP 1
#define XMLRPC_C 0
#if XMLRPC_CPP
#include
#include
#include
#elif XMLRPC_C
#include
#include
#include
#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;
}
运行结果:
服务器会报出这种错误,因为这个日志文件确实没有,我也没深究,不影响使用就行。