3

Ruby、C#、または Java クライアントのいずれかの各クライアントがすべての変更を登録済みクライアントのリストと同期する、分散イベント管理ツールを作成する任務を負っています。私はXML-RPC目標を達成するために使わなければなりません。私のチームと私は、XML-RPCクライアントとサーバーを各言語で作成しました。関連するソース コードを以下に示します。さらにコードが必要な場合は、お知らせください。

問題は、Java と C# を相互に通信できるようにすることです。Ruby は他のものと通信できますが、C# (および Java はまだテストしていない可能性があります) には、Ruby サーバーのアドレス指定に問題があります。問題はエンドポイントにあると思います。まず、いくつかのコードを示します。読むときは、コードが実際にはチームによって書かれており、命名規則が少し異なることに注意してください。

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 のクライアントを保持しません。これらはディクショナリに保存され、イベントを同期する必要が生じたときに使用されます。このような同期の 1 つは、変更の場合に発生します。

 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 サーバーには独自のクラスがあり、単純な呼び出しでインスタンス化されます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 クライアント 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) }

ルビーサーバー

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 のドキュメントも役に立ちません。助けが必要です!

4

1 に答える 1

0

WireSharkを使用して回線を通過するトラフィックを検査してみることができます。このツールを使用すると、異なるアプリケーション間で転送される実際のHTTPデータを確認できます。たぶん、これは、RubyとC#の間の通信に問題がある理由についてのヒントを提供します。

于 2010-10-25T16:27:37.680 に答える