.NET远程处理异常
这与引发.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