xmlrpc远程函数式服务调用,C++作为服务端,python、C++客户端远程调用函数

xmlrpc远程函数式服务调用,C++作为服务端,python、C++客户端远程调用函数,第1张

xmlrpc远程函数式服务调用,C++作为服务端,python、C++客户端远程调用函数

xmlrpc远程函数式服务调用,C++作为服务端,python、C++客户端通过http进行调用
  • C++编写服务端
  • C++编写客户端
    • C++客户端和服务端输出结果
  • Python编写客户端
    • 运行结果如下

C++编写服务端

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

// xmlrcp.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include 

#include 
#include 
#include 
#include 

#include 
#include 
#include 

class sampleAddMethod : public xmlrpc_c::method {
public:
	sampleAddMethod() {}
	void execute(xmlrpc_c::paramList const& paramList,
		xmlrpc_c::value* const retvalP = NULL) {


		int a = paramList.getInt(0);
		int b = paramList.getInt(1);
		*retvalP = xmlrpc_c::value_int(a + b);
		


	}

};
class sampleAddMethod1 : public xmlrpc_c::method {
public:
    sampleAddMethod1() {}

    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);
    }
};

//测试乱码
class GetEncoding : public xmlrpc_c::method {
public:
    GetEncoding() {}
    void execute(xmlrpc_c::paramList const& paramList,
        xmlrpc_c::value* const retvalP = NULL) {
        std::vector result;
        std::string inputstr = paramList.getString(0);
        printf("输入字符串:%s n", UTF8ToGBK(inputstr).c_str());
        std::cout << "输入字符串" << UTF8ToGBK(inputstr) << std::endl;
        std::wstring_convert> converter;
        std::string utf8_str = converter.to_bytes(L"该符号在函数_wmain 中被引用");
        //std::string c = base64Encode(utf8_str);
        //std::string str = "该符号在函数_wmain 中被引用";
        //std::vector ss = xmlrpc_c::bytesFrombase64(str);
        result.push_back(xmlrpc_c::value_string("hello"));
        result.push_back(xmlrpc_c::value_string("world"));
        //result.push_back(xmlrpc_c::value_bytestring(ss));
        //std::vector ss1 = xmlrpc_c::bytesFrombase64("English");
        //result.push_back(xmlrpc_c::value_bytestring(ss1));
        std::wstring_convert> converter1;
        std::string utf8_str1 = converter1.to_bytes(L"中文汉字乱码");
        result.push_back(xmlrpc_c::value_string(converter1.to_bytes(L"中文汉字乱码")));
        //result.push_back(xmlrpc_c::value_string(converter.to_bytes(("English"))));
        //result.push_back(xmlrpc_c::value_string(converter.from_bytes("中文汉字乱码")));
        result.push_back(xmlrpc_c::value_string(StringCoding("中文汉字乱码 hahah")));
        result.push_back(xmlrpc_c::value_string(StringCoding("中文汉字乱码")));
        result.push_back(xmlrpc_c::value_string(StringCoding("中文汉字乱码 ")));
        result.push_back(xmlrpc_c::value_string(StringCoding("Hello world 123")));
        result.push_back(xmlrpc_c::value_string(StringCoding("123456789")));
        result.push_back(xmlrpc_c::value_string(UnicodeToUTF8(StringToUnicode("中文汉字乱码"))));
        result.push_back(xmlrpc_c::value_string(UnicodeToUTF8(StringToUnicode("Hello world"))));
        //result.push_back(xmlrpc_c::value_string("中文汉字乱码"));
        result.push_back(xmlrpc_c::value_string(UnicodeToUTF8((L"中文汉字乱码"))));
        // byte[] byteData = Encoding.UTF8.GetBytes("你好中国");
         /
    }

    std::string UnicodeToUTF8(const std::wstring& wstr)
    {
        std::string ret;
        try {
            std::wstring_convert< std::codecvt_utf8 > wcv;
            ret = wcv.to_bytes(wstr);
        }
        catch (const std::exception& e) {
            std::cerr << e.what() << std::endl;
        }
        return ret;
    }
    std::wstring UTF8ToUnicode(const std::string& str)
    {
        std::wstring ret;
        try {
            std::wstring_convert< std::codecvt_utf8 > wcv;
            ret = wcv.from_bytes(str);
        }
        catch (const std::exception& e) {
            std::cerr << e.what() << std::endl;
        }
        return ret;
    }
    std::wstring ANSIToUnicode(const std::string& str)
    {
        std::wstring ret;
        std::mbstate_t state = {};
        const char* src = str.data();
        size_t len = std::mbsrtowcs(nullptr, &src, 0, &state);
        if (static_cast(-1) != len) {
            std::unique_ptr< wchar_t[] > buff(new wchar_t[len + 1]);
            len = std::mbsrtowcs(buff.get(), &src, len, &state);
            if (static_cast(-1) != len) {
                ret.assign(buff.get(), len);
            }
        }
        return ret;
    }
};
//测试连通性
class GetConnect : public xmlrpc_c::method {
public:
    GetConnect() {}
    void execute(xmlrpc_c::paramList const& paramList,
        xmlrpc_c::value* const retvalP = NULL) {
        printf("http服务连接成功n");
        std::wstring_convert> converter;
        std::string utf8_str = converter.to_bytes(L"http 服务连接成功");
        *retvalP = xmlrpc_c::value_string(utf8_str);
    }
};

//发送数组
class SendArray : public xmlrpc_c::method {
public:
    SendArray() {}
	void execute(xmlrpc_c::paramList const& paramList,
		xmlrpc_c::value* const retvalP = NULL) {

		xmlrpc_c::carray array1 = paramList.getArray(0);
		xmlrpc_c::carray array2 = paramList.getArray(1);
		
		int length = array1.size();
		std::vector result;
		for (int i = 0; i < length; i++)
		{
			int no1 = xmlrpc_c::value_int(array1[i]);
			int no2 = xmlrpc_c::value_int(array2[i]);
			printf("数据1:%d,数据2:%dn", no1, no2);
			std::vector entrust_value;
			entrust_value.push_back(array1[i]);
			entrust_value.push_back(array2[i]);
			xmlrpc_c::value arrayArray1 = xmlrpc_c::toValue(entrust_value);
			result.push_back(arrayArray1);
		}
		*retvalP = xmlrpc_c::value_array(result);
	}
};
int main()
{
	//std::cout << "Hello World!n";
	xmlrpc_c::registry myRegistry;
	xmlrpc_c::methodPtr const sampleAddMethodP = new sampleAddMethod();
	myRegistry.addMethod("add", sampleAddMethodP);
    xmlrpc_c::methodPtr const sampleAddMethodP1 = new sampleAddMethod1();
    myRegistry.addMethod("add1", sampleAddMethodP1);
	xmlrpc_c::methodPtr const send_array = new SendArray();
	myRegistry.addMethod("send_array", send_array);
    xmlrpc_c::methodPtr const coding = new GetEncoding();
    myRegistry.addMethod("coding", coding);
    //测试连通性
    xmlrpc_c::methodPtr const get_connnect = new GetConnect();
    myRegistry.addMethod("get_connnect", get_connnect);
    // 端口号、日志文件、保持连接时间(应该是秒?)、最大连接数
	xmlrpc_c::serverAbyss myAbyssServer(myRegistry, 8088,"",6000,100//,"xmlrpc_log"             // TCP port on which to listen		
		//"/tmp/xmlrpc_log"  // Log file		
	);
    //开启服务
	myAbyssServer.run();	// xmlrpc_c::serverAbyss.run() never returns	
	assert(false);
	return 0;
}

继承xmlrpc_c::method类的基类实现了一个调用的 execute方法,代码中共有5个类继承了xmlrpc_c::method的基类,也就是有5个http的接口,分别是接收参数、返回数据、乱码处理、测试连通性、计算加法等的demo,main方法中
注册了这五个接口到http的服务中

	xmlrpc_c::registry myRegistry;
	xmlrpc_c::methodPtr const sampleAddMethodP = new sampleAddMethod();
	myRegistry.addMethod("add", sampleAddMethodP);
    xmlrpc_c::methodPtr const sampleAddMethodP1 = new sampleAddMethod1();
    myRegistry.addMethod("add1", sampleAddMethodP1);
	xmlrpc_c::methodPtr const send_array = new SendArray();
	myRegistry.addMethod("send_array", send_array);
    xmlrpc_c::methodPtr const coding = new GetEncoding();
    myRegistry.addMethod("coding", coding);
    //测试连通性
    xmlrpc_c::methodPtr const get_connnect = new GetConnect();
    myRegistry.addMethod("get_connnect", get_connnect);

然后设置端口号、日志文件、保持连接时间(应该是秒?)、最大连接数

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

最后开启http服务:

//开启服务
	myAbyssServer.run();	// xmlrpc_c::serverAbyss.run() never returns
C++编写客户端

C++客户端代码如下

#include 
#include 
#include 
#include 
#include 


using namespace std;
using namespace xmlrpc_c;


string UTF8ToGBK(const string& str)
{
	string result;
	//获得临时变量的大小
	int i = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
	WCHAR* strSrc = new WCHAR[i + 1];
	MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, strSrc, i);
	//获得临时变量的大小
	i = WideCharToMultiByte(CP_ACP, 0, strSrc, -1, NULL, 0, NULL, NULL);
	LPSTR szRes = new CHAR[i + 1];
	WideCharToMultiByte(CP_ACP, 0, strSrc, -1, szRes, i, NULL, NULL);
	result = szRes;
	delete[]strSrc;
	delete[]szRes;
	return result;
}
wchar_t* StringToDword(const string& str)
{
	wstring result;
	//获取缓冲区大小,并申请空间,缓冲区大小按字符计算  
	int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), NULL, 0);
	TCHAR* buffer = new TCHAR[len + 1];
	//多字节编码转换成宽字节编码  
	MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.size(), buffer, len);
	buffer[len] = '';             //添加字符串结尾  
	//删除缓冲区并返回值  
	result.append(buffer);
	delete[] buffer;
	wchar_t* inputStr = new wchar_t;
	wcscpy(inputStr, result.c_str());
	return inputStr;
}

int main()
{
	string const serverUrl("http://localhost:8088/RPC2");
	//string const methodName= "add";
	//string const methodName("SuspectPersonManage");
	xmlrpc_c::clientSimple myClient;
	xmlrpc_c::value result;
	myClient.call(serverUrl, "get_connnect", &result);
	string ret_string = xmlrpc_c::value_string(result);
	string ss = UTF8ToGBK(ret_string);
	cout << ss << endl;
	printf("返回信息:%sn", UTF8ToGBK(ret_string).c_str());


	xmlrpc_c::value coding_result;
	//调用coding方法,w为宽字符串参数,
	myClient.call(serverUrl, "coding","w", &coding_result, StringToDword("中文乱码"));
	//返回值进行处理
	std::vector vector_result;
	xmlrpc_c::fromValue(vector_result, coding_result);
	for (int i = 0; i < vector_result.size(); i++)
	{
		string out = xmlrpc_c::value_string(vector_result[i]);
		cout <<"输出参数:"<< UTF8ToGBK(out) << endl;
	}

	
	xmlrpc_c::value add_result;
	myClient.call(serverUrl, "add", "ii", &add_result, 5, 7);
	int const sum((xmlrpc_c::value_int(add_result)));
	// Assume the method returned an integer; throws error if not

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

	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, paramLst, &result);
	xmlrpc_c::value add1_result;
	myClient.call(serverUrl, "add1", paramLst, &add1_result);
	cout << "Result of RPC (sum of 1 and 2): " << xmlrpc_c::value_int(add1_result) << endl;
	//发送集合参数
	std::vector input1;
	std::vector input2;
	for (int i = 0; i < 10; i++)
	{
		input1.push_back(i);
		input2.push_back(i+10);
	}
	xmlrpc_c::value arrayArray1 = xmlrpc_c::toValue(input1);
	xmlrpc_c::value arrayArray2 = xmlrpc_c::toValue(input2);
	xmlrpc_c::paramList paramLst1;
	paramLst1.addc(arrayArray1);
	paramLst1.addc(arrayArray2);
	xmlrpc_c::value array_result;
	myClient.call(serverUrl, "send_array", paramLst1, &array_result);
	//返回值进行处理
	std::vector send_result;
	xmlrpc_c::fromValue(send_result, array_result);
	for (int i = 0; i < send_result.size(); i++)
	{
		std::vector sub_send_result;
		xmlrpc_c::fromValue(sub_send_result, send_result[i]);
		for (int j = 0; j < sub_send_result.size(); j++)
		{
			cout << "输出参数:" << xmlrpc_c::value_int(sub_send_result[j]) << endl;
		}
		
	}
	system("pause");
	return 0;
}

客户端中演示了调用http服务的功能,使用http时代码中需要设置ip和端口号,然后直接通过调用函数的方式调用,演示了向服务端发送字符串、接收字符串数据、计算加法的示例。接收和发送中文字符串需要对字符编码进行处理,否则会出现乱码,UTF8ToGBK函数对接收到的字符串编码进行处理,StringToDword函数对发送的字符串编码进行处理,(服务端也会对接收到的字符串的编码进行处理,不处理的话服务端接收到的是乱码)

C++ 项目中包含xmlrpc的库,xmlrpc库可以参考 https://sourceforge.net/p/xmlrpc-c/code/HEAD/tree/

C++客户端和服务端输出结果


先运行服务端,在运行客户端,否则单独运行客户端会出错崩溃,代码中暂时没有对错误异常处理,输出的结果入截图,左边是服务端,右边是客户端,服务端中输出了客户端传入的数据,客户端中输出了服务端中返回的数据。

Python编写客户端

使用xmlrpc库进行编写,编写比较方便,代码如下,代码很简短,直接调用函数的方式调用http的服务

#!/usr/bin/python3
# -*- coding: utf-8 -*-
from xmlrpc.client import ServerProxy

server = ServerProxy("http://localhost:8088",encoding='utf-8',allow_none=True)
#调用coding方法,打印输出结果
print(server.coding('coding'))
#调用get_connnect方法
print(server.get_connnect())
#调用add方法
print('Result of RPC (sum of 5 and 7): {}'.format(server.add(5,7)))
print('Result of RPC (sum of 1 and 2): {}'.format(server.add1({'first':1,'second':3})))
#发送集合参数
input1 = []
input2 = []
for i in range(10):
    input1.append(i)
    input2.append(i+10)
ret = server.send_array(input1,input2)
print(ret)

运行结果如下


截图中包含客户端和服务端的输出结果

本文章主要参考以下博客,关于xmlrpc的介绍可以在下面的的博客中找到

https://blog.csdn.net/weixin_37348409/article/details/102327255
https://blog.csdn.net/qq_28453017/article/details/79931620

文章中C++工程代码和python代码已经上传到CSDN中,具体可以查看下载链接https://download.csdn.net/download/zckui/37257772,(C++项目工程只能编译成x86、32位的,编译成64位的会出错,windows上暂不支持64位编译)

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5098983.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-16
下一篇 2022-11-17

发表评论

登录后才能评论

评论列表(0条)

保存