XMLRPC 实现C++和C#交互.docx

上传人:b****5 文档编号:6369707 上传时间:2023-01-05 格式:DOCX 页数:9 大小:134.07KB
下载 相关 举报
XMLRPC 实现C++和C#交互.docx_第1页
第1页 / 共9页
XMLRPC 实现C++和C#交互.docx_第2页
第2页 / 共9页
XMLRPC 实现C++和C#交互.docx_第3页
第3页 / 共9页
XMLRPC 实现C++和C#交互.docx_第4页
第4页 / 共9页
XMLRPC 实现C++和C#交互.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

XMLRPC 实现C++和C#交互.docx

《XMLRPC 实现C++和C#交互.docx》由会员分享,可在线阅读,更多相关《XMLRPC 实现C++和C#交互.docx(9页珍藏版)》请在冰豆网上搜索。

XMLRPC 实现C++和C#交互.docx

XMLRPC实现C++和C#交互

一.方案介绍

 

        解决不同语言交互的方法有不少,对我了解的windows系统和.NET平台,有以下几种做法:

∙P/Invoke:

调用nativecpp的方法,处在同一个内存区间,访问方便,但包装困难,可能抛出运行时异常。

∙读写文件:

通过一头读文件,一头写文件的方式实现交互。

诸位别笑,本科时候我就用过这种方式解决问题。

∙命名管道/socket:

通过字节数组的方式实现交互,命名管道是windows系统提供的功能,可提供安全快捷的程序间交互。

socket不依赖于操作系统,只要给定包格式,在任何支持socket的语言平台下都能支持。

但缺点也很明显,如果交互复杂,那么解析这种byte[]数组将会非常复杂而且难以维护。

∙RPC:

又称之为远程过程调用,也是我们今天的主角。

     数据即程序,RPC说白了依旧是传递数据的过程,只是过程在代码上更像函数调用。

如下图:

     目前主流的RPC有两种:

XML和JSON。

XML是曾经的主角,兼容性更好。

但如今移动互联网要求数据流量要小,而XML的缺点也随之暴露出来,JSON由于节省数据(大大减少了包头和标记的开销),如今变得更受欢迎。

新浪微博API,如今全部升级为JSON了。

RPC的实质是http协议,它封装了底层实现的细节,能让我们将注意力放在应用逻辑的实现,而非建立连接这样的问题。

     RPC的优点很多,其中我最喜欢的是它的容器,声明一个Array,里面可以塞任何你想要的数据,int,string,double,struct甚至另外一个array都可以。

当然,不能传递抽象类或接口,毕竟不是同一内存区域。

     本文我们只介绍XML-RPC实现C++和C#两个应用程序之间的交互。

JSON的C#版本Jayrock对RPC的支持,尤其是对非ASP.NET环境几乎没有,连一篇像样的文档都找不到,所以我们仅仅讨论XML-RPC。

   

二.方案实现

              我们打算将C#作为客户端,C++作为服务器端。

  1.C++的服务器实现

              我们在VS2010中新建C++工程,将附件中的XMLRPC.LIB静态库拷入当前工程文件夹,设置当前工程为release模式。

同时在C++工程设置中,添加两个lib引用:

xmlrpc.lib,ws2_32.lib

之所以用release模式,是因为在debug模式下xmlrpc.lib库会出现如下的编译错误:

花了很久时间都没解决,如果有大神能帮助解决这个问题,请一定留言.

1>Alloutputsareup-to-date.

1>XmlRpc.lib(XmlRpcServer.obj):

errorLNK2038:

mismatchdetectedfor'_ITERATOR_DEBUG_LEVEL':

value'0'doesn'tmatchvalue'2'inHelloServer.obj

1>XmlRpc.lib(XmlRpcUtil.obj):

errorLNK2038:

mismatchdetectedfor'_ITERATOR_DEBUG_LEVEL':

value'0'doesn'tmatchvalue'2'inHelloServer.obj

1>XmlRpc.lib(XmlRpcServerMethod.obj):

errorLNK2038:

mismatchdetectedfor'_ITERATOR_DEBUG_LEVEL':

value'0'doesn'tmatchvalue'2'inHelloServer.obj

1>XmlRpc.lib(XmlRpcValue.obj):

errorLNK2038:

mismatchdetectedfor'_ITERATOR_DEBUG_LEVEL':

value'0'doesn'tmatchvalue'2'inHelloServer.obj

1>XmlRpc.lib(XmlRpcDispatch.obj):

errorLNK2038:

mismatchdetectedfor'_ITERATOR_DEBUG_LEVEL':

value'0'doesn'tmatchvalue'2'inHelloServer.obj

1>XmlRpc.lib(XmlRpcServerConnection.obj):

errorLNK2038:

mismatchdetectedfor'_ITERATOR_DEBUG_LEVEL':

value'0'doesn'tmatchvalue'2'inHelloServer.obj

1>XmlRpc.lib(XmlRpcSocket.obj):

errorLNK2038:

mismatchdetectedfor'_ITERATOR_DEBUG_LEVEL':

value'0'doesn'tmatchvalue'2'inHelloServer.obj

1>XmlRpc.lib(XmlRpcSource.obj):

errorLNK2038:

mismatchdetectedfor'_ITERATOR_DEBUG_LEVEL':

value'0'doesn'tmatchvalue'2'inHelloServer.obj

 

再将对应的库头文件加入到项目中,完成后如下图所示:

现在C#程序员普遍已经忘掉了怎么编译和使用C++静态库,我也是其中之一,如果你在上面几步遇到困难,不妨查看相关资料。

接下来,我们将开始编写工作代码:

首先是添加头文件引用,一般只要引用XMLRPC.H和XMLRPCVALUE.H即可,同时声明一个全局的XmlRpcServer服务。

(实在太不习惯C++中不new就能创建实例的语法了)

#include"RPC/XmlRpc.h"

#include"RPC/XmlRpcValue.h"

#include

#include

usingnamespaceXmlRpc;

//Theserver

XmlRpcServers;

添加主函数:

intmain()

{

/*if(argc!

=2){

std:

:

cerr<<"Usage:

HelloServerserverPort\n";

return-1;

}*/

//intport=atoi(argv[1]);

intport=2567;

XmlRpc:

:

setVerbosity(3);

//Createtheserversocketonthespecifiedport

s.bindAndListen(port);

//Enableintrospection

s.enableIntrospection(true);

//Waitforrequestsindefinitely

s.work(-1.0);

return0;

}

设置端口,绑定端口和启动.这些都没什么好说的。

值得注意的是调试等级,setVerbosity。

等级越高,输出信息越详细,最高等级可输出完整的xml交互文件供调试,但会严重拖累系统速度的。

在你测试功能完毕后,不妨将其设为0。

      接下来我们创建几个类,来实现服务端功能:

//Avariablenumberofargumentsarepassed,alldoubles,resultistheirsum.

classSum:

publicXmlRpcServerMethod

{

public:

Sum(XmlRpcServer*s):

XmlRpcServerMethod("Sum",s){}

voidexecute(XmlRpcValue¶ms,XmlRpcValue&result)

{

intnArgs=params.size();

doublesum=0.0;

for(inti=0;i

sum+=double(params[i]);

result=sum;

}

}sum(&s);

     所有功能都以继承于XmlRpcServerMethod类,同时改写其execute函数。

有点意思的是,这个XmlRPCValue数据类型,是类似C#的Dictionary,或JAVA的hashset。

 你可以通过类似C#索引器(字典)的方式,添加或读取该结构中的内容。

比如上面的params[i]。

由于代码简单,就不多做详细解释。

     类后跟了一个实例,sum(&s),这样就在服务器中注册了该功能。

   再创建一个类,来实现字符串操作:

//Oneargumentispassed,resultis"Hello,"+arg.

classHelloName:

publicXmlRpcServerMethod

{

public:

HelloName(XmlRpcServer*s):

XmlRpcServerMethod("HelloName",s){}

voidexecute(XmlRpcValue¶ms,XmlRpcValue&result)

{

std:

:

stringresultString="Hello,";

resultString+=std:

:

string(params[0]);

result=resultString;

}

}helloName(&s);

   也不多做解释了。

   我们再看一下,怎么存取RPC中的字典和数组,这才是精髓部分:

classStructData:

publicXmlRpcServerMethod

{

public:

StructData(XmlRpcServer*s):

XmlRpcServerMethod("GetStruct",s){}

voidexecute(XmlRpcValue¶ms,XmlRpcValue&result)

{

XmlRpcValueA;

A.setSize

(2);

A[0]["a"]=123;

A[0]["b"]=456;

A[1]["a"]=43;

A[1]["b"]=425;

result["a"]=A;

result["b"]=123;

}

}structData(&s);

  设置字典时,是不需要指定其size的,但若设定的是数组,则必须使用setsize方法设定其大小。

字典的值也可包含另外一个XmlRpcValue结构体。

  RPC中可以很好的处理字符串,int,double,datetime类型,但枚举类型的支持并不好,我建议直接传int.

  

 完成了这三个服务后,我们来编写C#的客户端。

 

   2.C#RPC客户端实现:

        新建一个C#工程,创建以下的接口类:

publicinterfaceIRPCMethod

{

[XmlRpcMethod("HelloName")]

stringHelloName(stringName);

[XmlRpcMethod("Sum")]

doubleSum(doublea,doubleb);

[XmlRpcMethod("GetStruct")]

XmlRpcStructGetStruct();

}

当然,要引用CookComputing.XmlRpc库。

使用接口类的作用是剥离RPC对系统的影响,让系统可以“透明的”调用RPC代码。

值得注意的是,名称必须与C++中的名称一致,否则会出现找不到方法的异常。

   我们注册客户端服务:

varchnl=newHttpChannel(null,newXmlRpcClientFormatterSinkProvider(),null);

ChannelServices.RegisterChannel(chnl,false);

varsvr=(IRPCMethod)Activator.GetObject(typeof(IRPCMethod),"http:

//localhost:

2567/");

Console.WriteLine("成功注册信道");

stringret=svr.HelloName("haha");

Console.WriteLine("调用helloName方法:

"+ret);

doubleresult=svr.Sum(23,18);

Console.WriteLine("调用Sum方法:

"+result.ToString());

XmlRpcStructresult2=svr.GetStruct();

  至于result2结构体,你可以通过调试来查看具体的运行结果。

  

在服务器端,可以看到调用所花费的流量和方法名称。

三.其他

这里我们关注一些额外的问题:

1.流量

     RPC的一种场景是本地不同程序调用,这种情况下速度很快。

但在跨机器或是移动设备上,就必须考虑流量因素了。

XML的“性价比”并不高:

xmlversion="1.0"?

>

echo

HelloChris

123

 实际的有用数据,仅占所有字节数的5%,甚至更少,除非是大批量的传输本文数据。

如果是流量敏感,推荐使用JSON.

   2.性能

   我们当然要关心,RPC在本机调用会有多快?

和哪些因素敏感?

笔者配置是i72600K, 8GBDDR,Gbps网络适配器,VS的debug模式。

在执行Sum操作时,一千次耗时4.3ms。

在执行更复杂的结构体传递(大概有20个double,三个string,两个int时),千次耗时5.8ms。

      因此,可以得知,XML的转换和解析几乎不耗时,建立连接后,执行一次在ms量级,对数据结构复杂程度不敏感,因此,若是实时性敏感应用,建议一次性多传些数据。

 3.兼容性

      笔者发现,RPC的兼容性并不太好,在和JAVA采用RPC交互时,就遇到了困难,”XML解析异常”。

JSON的的兼容性不见得比XML更好,实际操作更是问题多多。

涉及RPC的社区,普遍文档较少,例子不全,出现问题也不好排查,更没有太多跨语言的RPC实例。

因此,如果你能用P/Invoke,还是推荐用直接调用的做法。

RPC肯定还是比byte流的socket方便很多。

  四.总结和源代码下载

      RPC将原本复杂的数据传输问题简化了,使我们从复杂的数据包结构,JAVA和C的double编码和socket传输中脱离出来,提供了更简单方便的方案。

但必须看到,它并不完善,我们只能一步步的探索。

 

    另外想问一句,Unity3D的RPC是何种格式?

     有任何问题,欢迎随时交流。

     

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1