Remoting和丢失频道接收器

时间:2009-11-01 18:13:03

标签: .net remoting appdomain

我遇到了一个远程例外:

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

this blog entry我找到了最好的解释原因:

  

第二种情况更加模糊。这个   发生在客户端拨打电话的地方   到服务器,服务器返回一个   对象引用,然后是客户端   对引用的对象进行调用   在服务器上。如果引用   对象位于辅助AppDomain上   服务器上面的异常可能是   抛出。如果问题发生了   是因为只有频道注册   适用于其中的AppDomain   RegisterChannel被调用而没有   频道已经注册了   辅助AppDomain。物体   引用返回给客户端   指向辅助中的对象   AppDomain,而不是它的代理   主AppDomain,所以没有   客户与客户之间的渠道   辅助AppDomain跨越   电话可以通过。解决方案:注册一个   辅助AppDomain中的频道   引用的对象存在。

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

我认为代理就足以跨越appdomain边界。我真的必须在插件和应用程序之间创建通道吗?这似乎不对,所以我必须遗漏一些东西。

3 个答案:

答案 0 :(得分:4)

扩展@ 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时,赞助商会远程连接到服务器端。但是,如果服务器没有到客户端的远程通道,则会失败。

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

答案 1 :(得分:2)

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

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

如果您需要双向进行,例如:将日志对象传递给“服务器”以便接收连续的日志反馈,您必须在两端注册服务器通道,因为客户端突然也为对象提供服务:

class MyLogger : MarshalByRefObject
{
    public Log(string text) { ... }
}

MyLogger logger = new MyLogger();
proxyObj.LongRunningCommand(logger);

答案 2 :(得分:0)

对于那些在&#34上搜索的人;这个远程代理没有信道接收器......"错误,从VBScript调用VB.NET COM包装库时出现此错误。所有这些都在同一台Windows 7机器上,因此应该没有客户端服务器问题。最终我发现错误是由于我传递了一大堆充满字符串的arraylists,而不是填充单曲,这就是我所调用的函数所期望的。我不明白为什么会收到此错误,但希望它可能有助于此人收到此错误。