質問

これは、.NET リモート処理例外がスローされるときの話です。MSDN を見ると、リモート処理で問題が発生した場合にリモート処理例外がスローされることが記載されています。サーバーが実行されていない場合、ソケット例外が発生しますが、これは問題ありません。

私が理解しようとしているのは次のとおりです:リモーティング例外が発生したということは、サーバーが確実に稼働していることを示していますか?そうであれば、問題は解決します。そうでない場合:リモーティング例外がクライアント側で発生したのかサーバー側で発生したのかを確認する方法はありますか?

アップデート:

私が解決しようとしている問題は、サーバーが最初にダウンし、その後クライアントがサーバーにメッセージを送信することです。「接続を確立できませんでした...」というソケット例外が表示されるようになりましたが、これは問題ありません。

サーバーが利用可能かどうかを確認するために、サーバーに定期的にメッセージを送信するスレッドがあります。さて、サーバーが起動し、その時点で問題ない応答を取得することも、何らかの例外を取得することもできますが、おそらくそれはリモート例外です。それで、私が聞きたいのは次のようなことです。メッセージを受け取らず、リモート例外が発生した場合、サーバーが稼働していてもこの例外が発生する可能性はありますか?

私が行っているのは、何もせずに返すリモート オブジェクトのメソッドを呼び出すことだけです。例外がなければ大丈夫です。ここで、リモート処理例外が発生し、そのリモート処理例外がサーバー上で発生したことがわかっていれば、例外が発生したにもかかわらずサーバーに接続していることがわかります。

役に立ちましたか?

解決

リモート例外が発生しても、サーバーが稼働していることが保証されるわけではありません。他の何かがそのポートで実行されリッスンしている場合、接続は成功し、ソケット例外は発生しません。この場合に何が起こるかは、実際に接続を取得したアプリケーションがどのように動作するかによって異なりますが、おそらくクライアントでリモート例外が生成されることになります。

これを確認するにはもう少し調査が必要ですが、リモート例外はクライアントとサーバー間の通信に問題があることを示していると考えられます。したがって、それを生成したのは「クライアント側」または「サーバー側」ではありません。つまり、二人は楽しく話していなかったので、どちらかが原因である可能性があります。

他のヒント

リモート境界を越えてスローされるカスタム例外タイプを使用する場合は、これらのタイプを「[Serializable]」としてマークしてください。正確なエラー メッセージは思い出せませんが、初めてこのエラー メッセージを見たときは、一日のほとんどの時間、困惑しました。

また、ヒントとして、TargetInvocationException には、InnerException プロパティに REAL 例外が埋め込まれていることがよくあります。「呼び出しのターゲットによって例外がスローされました」ほど役に立たないものはありません。

正しいメッセージを送信し、サーバーが受信したメッセージも正しいことを確認してください。アサーションを使用します (これは、契約による設計と呼ばれます)。そのような可能性がある場合は、サーバー側とクライアント側を同時にデバッグしてみてください。(2 つの VS インスタンスを同時に実行)

前回のリモート アプリケーションのソース コードにはアクセスできませんでしたが、覚えている限りでは、発生した例外によってサーバーが稼働しているかどうかを明確に知る方法は見つかりませんでした。
ネットワークが存在するかどうかを確認し、存在しない場合はユーザーに警告しました (Environment クラスのメソッドだと思います)。

サーバー側のアプリケーション ロジックが例外をスローした場合、クライアントにマーシャリングして何が起こったのかを通知できる必要があります。これをテストするには、リモート オブジェクトのメソッドの 1 つで意図的に例外をスローします。次に、例外を期待してクライアント側からその特定のメソッドを呼び出します。

HttpChannel channel = new HttpChannel();
ChannelServices.RegisterChannel(channel);

IMyRemoteObject obj = (IMyRemoteObject) Activator.GetObject(
    typeof(IMyRemoteObject),
    "http://localhost:1234/MyRemoteObject.soap");
Console.WriteLine("Client.Main(): Reference to rem.obj. acquired");
    int tmp = obj.GetValue();
    Console.WriteLine("Client.Main(): Original server side value: {0}",tmp);
Console.WriteLine("Client.Main(): Will set value to 42");

try
{
    // This method will throw an ApplicationException in the server-side code.
    obj.SetValue(42);
}
catch (Exception ex)
{
    Console.WriteLine("=====");
    Console.WriteLine("Exception type: " + ex.GetType().ToString());
    Console.WriteLine("Message: " + ex.Message);
    Console.WriteLine("Source: " + ex.Source);
    Console.WriteLine("Stack trace: " + ex.StackTrace);
    Console.WriteLine("=====");
}

このように例外を受け取ることが期待できます

=====
Exception type: System.ApplicationException
Message: testing
Source: Server
Stack trace:
Server stack trace:
   at Server.MyRemoteObject.SetValue(Int32 newval) in i:\projects\remoting.net\ch03\01_singlecallobjects\server\server.cs:line 27
   at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(MethodBase mb, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg, Int32 methodPtr, Boolean fExecuteInContext)

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 General.IMyRemoteObject.SetValue(Int32 newval)
   at Client.Client.Main(String[] args) in i:\projects\remoting.net\ch03\01_singlecallobjects\client\client.cs:line 29
=====

サーバー側のスタック トレースにより、ソースがサーバーにあることがわかります。

さて、このように説明しましたが、リモート処理に TCP を使用していると思います。HTTP 経由の場合、(TCP ネットワーク ポート) サーバーへの接続に失敗したときに WebException がスローされるためです。サーバーが、指定された TCP ポートにチャネルを登録するためのアプリケーション プログラムを起動していない場合、SocketException が発生します。結局のところ、サーバーはそのポートをリッスン/応答していないのに、クライアントはどうやってソケット接続を確立できるのでしょうか?

ただし、RemotingException が発生した場合は、 ない サーバーが適切なリモート アプリケーションを正常に実行していることを意味します。ポート 80 (IIS) など、間違ったポートの間違った URI に接続してテストすることもできます。

IMyRemoteObject obj = (IMyRemoteObject) Activator.GetObject(
    typeof(IMyRemoteObject),
    "tcp://localhost:80/MyRemoteObject.rem");

これにより、クライアントはポート 80 への TCP 接続を確立できますが、呼び出しに応答しているのは Remoting アプリではなく IIS であるため、RemotingException が発生します。IIS はリモート呼び出しを直接処理できません。そうは言っても、RemotingException はクライアント側の問題を意味する場合もあります。このブログ記事は理解を深めるのに役立つかもしれません。

http://www.cookcomputing.com/blog/archives/000308.html

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top