繁体   English   中英

使用XML-RPC对使用C#,Ruby和Java编写的分布式应用程序进行编程

[英]Programming a distributed application written in C#, Ruby and Java using XML-RPC

我的任务是编写一个分布式事件管理工具,其中每个客户端(Ruby,C#或Java Client)都会将所有更改与已注册客户端列表同步。 我必须使用XML-RPC来实现目标。 我和我的团队用各种语言编写了一个XML-RPC客户端和服务器,并在下面提供了相关的源代码。 如果您需要更多代码,请告诉我们。

问题是我可以让Java和C#相互通信。 Ruby可以与其他人进行通信,但C#(可能还有Java,尚未测试)在解决Ruby服务器时遇到问题。 我想问题出在Endpoint上。 首先让我给你一些代码。 阅读时请注意代码实际上是由团队编写的,命名约定有所不同:

C#客户端

Uri _address = new Uri("http://" + _s + ":8000/xmlrpc/EventManagerService");
ChannelFactory<IEventManagerWCF_XML_RPC> _factory = new ChannelFactory<IEventManagerWCF_XML_RPC>(new WebHttpBinding(WebHttpSecurityMode.None), new EndpointAddress(_address));
_factory.Endpoint.Behaviors.Add(new XmlRpcEndpointBehavior());
IEventManagerWCF_XML_RPC _proxy = _factory.CreateChannel();

_proxy不会保留给定URI的客户端。 它们存储在字典中,并在需要同步事件时使用。 在修改的情况下会发生一次这样的同步;

 foreach(IEventManagerWCF_XML_RPC proxy in this.peers.Values)
        proxy.modify(_id, _field, _newValue);

这是IEventManagerWCF_XML_RPC接口的摘录;

 [OperationContract(Action = "EventManagerService.modify")]
 bool modify(int id, string field, string newValue);

C#XML RPC服务

 Uri _baseAddress = new Uri("http://localhost:8000/xmlrpc");
 _eventManagerHost = new ServiceHost(typeof(EventManagerService), _baseAddress);
     try
     {
     ServiceEndpoint epXmlRpc = _eventManagerHost.AddServiceEndpoint(typeof(IEventManagerWCF_XML_RPC), new WebHttpBinding(WebHttpSecurityMode.None), "EventManagerService");
     epXmlRpc.Behaviors.Add(new XmlRpcEndpointBehavior());

     ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
     smb.HttpGetEnabled = true;
     _eventManagerHost.Description.Behaviors.Add(smb);
     _eventManagerHost.Open();
     }
     catch (CommunicationException ce)
     {
     Console.WriteLine("An exception occurred: {0}", ce.Message);
     _eventManagerHost.Abort();
     }

我猜这里没什么特别的。 让我们转到Java代码!

Java客户端

XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
try {
  config.setServerURL(new URL("http://"+ip+":8000/xmlrpc/EventManagerService"));

} 
catch (MalformedURLException e) {  
  e.printStackTrace();
}

config.setEnabledForExtensions(true);  
config.setConnectionTimeout(60 * 1000);
config.setReplyTimeout(60 * 1000);      
XmlRpcClient client = new XmlRpcClient();
client.setTransportFactory(new XmlRpcCommonsTransportFactory(client));
client.setConfig(config);
xmlRpcPeers.put(ip, client); 

xmlRpcPeers现在拥有不同的客户端。 它们被称为如下;

for(XmlRpcClient peer : this.xmlRpcPeers.values())
  {
   try {
    peer.execute("EventManagerService.modify", params);
   } catch (Exception e) {
    e.printStackTrace();
   }
  }

Java Server拥有自己的类,并通过简单的new调用进行实例化;

public class Server extends Thread{

/**
* Server port
*/
  private static final int port = 8000;

  /**
   * Starts the XML-RPC server
   */
  public void run(){
   WebServer webServer = new WebServer(port);        
   XmlRpcServer xmlRpcServer = webServer.getXmlRpcServer();   

   PropertyHandlerMapping phm = new PropertyHandlerMapping();
   try
   {
    phm.addHandler("EventManagerService", lu.uni.binfo.ds.EventManager_Java.EventManagerService.class);
   } 
   catch (XmlRpcException e1) 
   {
    e1.printStackTrace();
   }           
      xmlRpcServer.setHandlerMapping(phm);        
      XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl) xmlRpcServer.getConfig();
      serverConfig.setEnabledForExtensions(true);
      serverConfig.setContentLengthOptional(false);          
      try 
      {
        webServer.start();
      } 
      catch (IOException e) 
      {
        e.printStackTrace();
      }
   }
}

到目前为止,一切似乎都很好。 将Ruby添加到混合中是最麻烦的。 这是相关的代码;

Ruby Client Ruby客户端也存储在字典中。 它的填充如下;

@devices_XMLRPC[key] = EventManagerClient_XMLRPC.new(tokens[0]).device

该类的代码是:

class EventManagerClient_XMLRPC
  @uri
  @device
  attr_accessor :uri, :device

  def initialize(uri)
    @uri = uri
    @device = XMLRPC::Client.new2(
            uri="http://" << @uri.to_s << ":8000/xmlrpc/EventManagerService", proxy=nil, timeout=30)
  end
end

对修改进行同步的调用如下所示:

@devices_XMLRPC.each_value { |client| client.call("EventManagerService.modify", tokens[0], field, value) }

Ruby服务器

server = XMLRPC::Server.new(8000, "127.0.0.1")
server.add_handler("xmlrpc/EventManagerService", EventManagerService.instance)
puts "Server ready!"
server.serve

EventManagerService类:

class EventManagerService
  include Singleton
  @manager

  def initialize()
    @manager = EventManager.instance
  end

  def modify(id, field, newValue)
      puts "modify called"
      @manager.modify([id, field, newValue], 1)
  end

end

EventManager是所有逻辑所在的类。

尝试从C#与Ruby通信时出现的错误是EndPointNotFoundException

There was no endpoint listening at http://ip:8000/xmlrpc/EventManagerService that could accept the message.[...]

我试图摆弄端点声明,但似乎无法让它工作。 Ruby文档也没有帮助。 我需要帮助!

您可以尝试使用WireShark检查通过线路的流量 使用此工具,您将能够看到在不同应用程序之间传输的实际HTTP数据。 也许这提供了一个提示,说明为什么你在Ruby和C#之间进行通信时遇到问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM