1

アクティベーターを介して2つの異なるリモートプロキシを要求する必要があるserver\clientアプリケーションがあります。

チャネルを作成せずにリモートオブジェクトを要求しActivator.GetObject、後でチャネルを作成して別のオブジェクトを取得しようとすると、2番目のオブジェクトが失敗するという状況に遭遇しました。問題を実証するためのサンプルアプリケーションを示しましょう。

2つのリモートオブジェクトは次のとおりです。

namespace HelloRemoteObject
{
    public class FirstObject : MarshalByRefObject
    {
        public String FirstObjectMethod()
        {
            return "FirstObjectMethod";
        }
    }

    public class SecondaryObject : MarshalByRefObject
    {
        public String SecondObjectMethod()
        {
            return "Secondary object method return string";
        }
    }
}

これがサーバーです。特定のポートにhttpサーバーチャネルを登録して待機します。

public static int Main(string[] args)
{
    // register the channel
    IDictionary properties = new Hashtable
                                    {
                                        {"timeout", 1000},
                                        {"port", 9099}
                                    };

    var serverChannel = new HttpServerChannel(properties, new BinaryServerFormatterSinkProvider());
    ChannelServices.RegisterChannel(serverChannel, false);

    // register two known types
    RemotingConfiguration.RegisterWellKnownServiceType(typeof(FirstObject), "FirstObjectUri", WellKnownObjectMode.Singleton);
    RemotingConfiguration.RegisterWellKnownServiceType(typeof(SecondaryObject), "SecondaryObjectUri", WellKnownObjectMode.Singleton);

    Console.WriteLine("Hit <enter> to exit...");
    Console.ReadLine();
    return 0;
}

そして、これがクライアントです。引数を渡すと、最初に名前付きチャネルが登録されます。次に、2つのリモートプロキシを取得し、それらに対して1つのメソッドを呼び出します。引数を指定しない場合は、最初に最初のオブジェクトへのプロキシを取得し、次に2番目のプロキシ用のチャネルを作成してから、2つを操作してみます。

static void Main(string[] args)
{
    var registerChannelFirst = args.Length > 0;
    if(registerChannelFirst)
    {
        Console.WriteLine("Registering channel first");

        RegisterHttpChannel();
    }
    else
    {
        Console.WriteLine("Letting Activator.GetObject register an http client channel by default");
    }

    var firstRemoteObject = (FirstObject)Activator.GetObject(typeof(FirstObject), "http://127.0.0.1:9099/FirstObjectUri");

    if(!registerChannelFirst)
    {
        RegisterHttpChannel();
    }

    var secondRemoteObject = (SecondaryObject)Activator.GetObject(typeof(SecondaryObject), "http://127.0.0.1:9099/SecondaryObjectUri", );

    Console.WriteLine(firstRemoteObject.FirstObjectMethod());
    Console.WriteLine(secondRemoteObject.SecondObjectMethod());
}

private static void RegisterHttpChannel()
{
    // register the channel
    IDictionary properties = new Hashtable
                                    {
                                        {"name" , "ChannelName"}
                                    };
    var clientChannel = new HttpClientChannel(properties, new BinaryClientFormatterSinkProvider());

    ChannelServices.RegisterChannel(clientChannel, false);
}

最初にチャネルを登録すると、アクティブ化する前に、すべてが正常に機能します。

アクティベーターを最初に移動させてから2番目のオブジェクトを取得すると、例外が発生します。

2つのオブジェクトをアクティブ化しようとせず、アクティベーターにオブジェクトを取得させるだけの場合は、それも機能します。これがなぜなのか知りたいのですが?

チャネルのプロパティを気にしないと言うと、1つのチャネルを簡単に作成してそれを実行できますが、一方のオブジェクトがチャネルのタイムアウトを利用する必要があるが、もう一方のオブジェクトはそれを使用する場合は、興味があります。そうではなく、2つの別々のチャネルを作成する必要があります。次に、オブジェクトをチャネルにバインドする方法はありますか?

また、リモーティングがwcfの道を進んでいることも認識していますが、それは今のところ私にとっての選択肢ではありません。

4

1 に答える 1

0

したがって、ここでの解決策は、常にチャネル名を登録することだと思います。チャネル名を登録すると、出力は次のようになります(の名前ChannelNameの出力ですChannelServices.RegisteredChannels

Registering channel first
ChannelName
FirstObjectMethod
Secondary object method return string

アクティベーターの実行後にチャネルを登録すると、独自の内部デフォルトチャネルが作成されたように見えます

Letting Activator.GetObject register an http client channel by default
http client, ChannelName

Unhandled Exception: System.Runtime.Remoting.RemotingException: System.ArgumentNullException: No message was deserialized prior to calling the DispatchChannelSink.
Parameter name: requestMsg
at System.Runtime.Remoting.Channels.DispatchChannelSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream)
at System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream)
at System.Runtime.Remoting.Channels.Http.HttpServerTransportSink.ServiceRequest(Object state)
at System.Runtime.Remoting.Channels.SocketHandler.ProcessRequestNow()


Server stack trace:


Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at HelloRemoteObject.FirstObject.FirstObjectMethod()
   at HelloClient.HelloClient.Main(String[] args) in 

そのため、2つの登録済みhttpチャネルがあると何かが混乱しています。.netソースをステップスルーしたはずですが、問題が発生していました。

于 2012-09-03T16:46:04.860 に答える