.NET远程处理异常

时间:2020-03-05 18:56:22  来源:igfitidea点击:

这与引发.NET远程处理异常有关。如果我们看一下MSDN,它将提到当远程处理出现问题时,将引发远程处理异常。如果我的服务器未运行,则会收到套接字异常,这很好。

我要弄清楚的是:是否获得远程异常是否可以确保我的服务器已启动并正在运行?如果是,那就可以解决问题。如果不是:是否有办法确定远程处理异常是起源于客户端还是服务器端?

更新:

我要解决的问题是服务器最初已关闭,然后客户端将一些消息发送到服务器。现在,我得到一个套接字异常,说"无法建立连接...",这很好。

有一个线程会定期向服务器发送消息,以查看服务器是否可用。现在,服务器启动了,到那时,我们可以得到很好的响应,或者可以得到一些异常,并且很可能是远程异常。所以,我想问的是:万一我没有收到消息并且收到远程异常,是否有可能服务器已启动并正在运行,而我仍然收到此异常?

我要做的只是在远程对象上调用什么都不做并返回的方法。如果没有例外,那我很好。现在,如果存在远程异常,并且如果我知道远程异常发生在服务器上,那么尽管知道有异常,但我已连接到服务器。

解决方案

回答

尝试确保我们发送了正确的消息,并且服务器收到的消息也是正确的,例如使用断言(称为按合同设计)。
如果有这种可能性,请尝试同时调试服务器端和客户端。 (同时运行两个VS实例)

回答

我没有访问上一个远程应用程序的源代码,但据我所记得,我们还无法找到一种确定服务器是否摆脱了任何异常的方法。
我们确实检查了网络是否存在并警告用户是否存在(我认为是Environment类的一种方法)。

回答

获取远程处理异常不能保证服务器已启动并正在运行。如果碰巧在该端口上运行并监听其他内容,则连接将成功,并且我们不会收到套接字异常。在这种情况下,将发生什么情况取决于实际建立连接的应用程序的行为,但是最终可能会在客户端中生成远程异常。

要验证这一点,还需要进行更多调查,但是我相信远程处理异常表明客户端和服务器之间的通信存在问题,因此没有"客户端"或者"服务器端"生成该异常。这意味着两个人的讲话并不愉快,这可能是由任何一个引起的。

回答

如果服务器端应用程序逻辑抛出异常,则它应该能够封送给客户端,以使其了解发生了什么。我们可以通过在远程对象的方法之一中故意抛出异常来进行测试。然后从客户端调用该特定方法,期望发生异常:

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_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_singlecallobjects\client\client.cs:line 29
=====

它应该告诉我们Source在服务器上,并带有服务器端堆栈跟踪。

回答

如果打算使用自定义异常类型在远程​​绑定边界上抛出,请确保将这些类型标记为" [可序列化]"。我不记得确切的错误消息,但是在我第一次看到它的时候,它困扰了我一天的大部分时间。

另外,只是提示,TargetInvocationException通常在其InnerException属性中嵌入REAL异常。没有什么比"调用的目标抛出异常"更无用了。

回答

好的,现在我们已经这样说了,我假设我们正在使用TCP进行远程处理,因为如果通过HTTP进行连接,则将是在无法连接到(TCP网络端口)服务器时抛出的WebException。当服务器尚未启动应用程序以在该指定的TCP端口上注册通道时,我们将获得SocketException。毕竟,服务器没有在侦听/响应该端口,客户端如何进行套接字连接?

但是,如果我们收到RemotingException,则不一定表示服务器正常运行了正确的Remoting应用程序。我们可以通过在错误的端口(例如端口80(IIS))上连接到错误的URI进行测试。

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

这将导致RemotingException,因为尽管客户端可以建立与端口80的TCP连接,但是IIS响应了该调用而不是Remoting应用程序。 IIS无法直接处理远程调用。话虽这么说,RemotingException也可能意味着在客户端出现问题。这篇博客文章可以更好地理解。

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