【问题标题】:Remoting and missing channel sinks远程处理和缺少通道接收器
【发布时间】:2010-12-12 02:05:09
【问题描述】:

我遇到了远程处理异常:

“此远程代理没有通道接收器,这意味着服务器没有注册的服务器通道正在侦听,或者此应用程序没有合适的客户端通道与服务器通信。”

原因最好用this blog entry来解释我发现:

第二种情况比较模糊。这 发生在客户打电话的地方 到服务器,服务器返回一个 对象引用,然后是客户端 调用被引用的对象 在服务器上。如果引用的 对象位于辅助 AppDomain 上 服务器上面的异常可能是 抛出。如果出现问题 是因为只有频道注册 适用于其中的 AppDomain RegisterChannel 被调用并且没有 频道已注册在 辅助应用程序域。物体 返回给客户端的引用 指向二级中的对象 AppDomain,不在其代理中 主 AppDomain,因此没有 客户端和客户端之间的通道 次要 AppDomain 通话可以通过。解决方法:注册一个 辅助 AppDomain 中的通道 被引用的对象存在于哪个位置。

这确实适合我的场景,因为我有一项服务可以将插件加载到单独的应用程序域中。对象实例(在所有程序集引用的程序集中定义的接口的实现)在辅助应用程序域中创建并由服务引用(跨应用程序域,因此服务具有代理引用)。然后服务将这些代理引用返回给应用程序。应用程序和服务之间有注册的通道,但插件和应用程序之间没有。

我认为代理足以跨越 appdomain 边界。我真的必须在插件和应用程序之间创建通道吗?这似乎根本不对,所以我一定是遗漏了什么。

【问题讨论】:

    标签: .net remoting appdomain


    【解决方案1】:

    扩展@RonCohen 的回答 -

    在服务器上,通常以有趣的方式创建一个完整的频道(特别是如果您想解决 TypeLevelFilter 问题,ala https://stackoverflow.com/a/9268223/344638):

    BinaryServerFormatterSinkProvider serverProvider;
    BinaryClientFormatterSinkProvider clientProvider;
    Hashtable properties = new Hashtable();
    
    serverProvider = new BinaryServerFormatterSinkProvider();
    serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
    
    clientProvider = new BinaryClientFormatterSinkProvider();
    
    properties.Add( "port", 8080 );
    
    this.chan = new TcpChannel( properties, clientProvider, serverProvider );
    
    ChannelServices.RegisterChannel( this.chan, true );
    

    假设您在客户端使用赞助商。如果你不这样做,并且客户端有一段时间没有调用远程对象,服务器将丢弃该对象:

    Object '/70c96e17_02a8_4e1a_a040_7b671b4a66b4/3fssua+asfozgeqqkrjql+4k_1.rem' has been disconnected or does not exist at the server.
    

    因此,您正在使用赞助商,然后服务器偶尔会调用赞助商来更新远程对象。但!现在服务器有一个远程对象 - 当赞助者调用ILease.Register 时,赞助者被远程到服务器端。但是,如果服务器没有到客户端的远程处理通道,则会失败。

    因此,与服务器必须向客户端公开远程通道以使客户端访问远程对象的方式相同,客户端必须向服务器公开远程通道以使服务器能够访问远程对象像赞助商。最后,我的客户端和服务器端都有相同的通道构造代码(上图),除了我在每一端使用不同的端口号。

    【讨论】:

      【解决方案2】:

      为了在从 MarshalByRefObject 派生的对象上跨 appdomains 使用远程处理,有必要在两端创建通道。因此,您必须在每个 appdomain 中创建频道。有有效的渠道可以在同一台机器上本地执行此操作,例如IPC 通道(使用命名管道)。

      如果通信是“单向”的,即只有一方在代理上调用方法,则您在此处注册一个客户端通道,并在创建对象的一侧注册服务器通道。

      如果您需要双向使用,例如将日志对象传递给“服务器”为了接收持续的日志反馈,您必须在两端注册一个服务器通道,因为客户端突然也服务对象:

      class MyLogger : MarshalByRefObject
      {
          public Log(string text) { ... }
      }
      
      MyLogger logger = new MyLogger();
      proxyObj.LongRunningCommand(logger);
      

      【讨论】:

        【解决方案3】:

        对于那些搜索“此远程代理没有通道接收器...”错误的人,我在从 VBScript 调用 VB.NET COM 包装库时收到此错误。所有这些都在同一台 Windows 7 机器上,所以应该没有客户端服务器问题。最终,我发现错误是由于我传递了一个充满字符串的数组列表而不是单数列表,这是我调用的函数所期望的。我不明白为什么我会收到此错误,但希望它可以帮助有人收到此错误。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-11
          • 1970-01-01
          • 1970-01-01
          • 2012-12-12
          相关资源
          最近更新 更多