【问题标题】:.NET Remoting: How to handle disconnected objects.NET Remoting:如何处理断开连接的对象
【发布时间】:2010-10-26 20:21:21
【问题描述】:

首先,让我解释一下我的设置。我的服务器设置为 Marshaled 单例对象:

 RemotingServices.Marshal(lsServer, ServerObject.objectUri);

为了实现从服务器到客户端的双向通信,客户端激活一个ServerObject,然后传入自己的ClientObject(也是MarshalByRefObject),服务器使用ClientObject与客户端对话:

var lsClient = new ClientObject();

var lsServer = (ServerObject)Activator.GetObject(typeof(ServerObject), url);
lsServer.attach(lsClient);

当调用attach方法时,服务器获取ClientObject并将其存储在一个List中:

public void attach(ClientObject client) {
    clientList.Add(client);
}

然后,服务器可以在 ClientObject 上调用一个名为“SendMessage”的方法,与列表中的每个客户端进行通信:

foreach(var c in clientList) {
    c.SendMessage("Hello");
}

在遇到断开连接的客户端之前,这非常有效。在这种情况下,会引发有关客户端拒绝连接的错误。我可以捕捉到错误,但问题是我无法从服务器列表中删除对 ClientObject 的引用。每当客户端断开连接时,以下内容都会重新引发“连接被拒绝”异常:

clientList.Remove(badClient);

有几个问题:

1- 有没有办法在不捕获错误的情况下检测客户端的连接状态?

2- 当我检测到客户端已断开连接时,为什么尝试从服务器列表中删除对象似乎与客户端“通信”(从而导致再次引发异常?)

编辑

正如 Patrick 在下面指出的,从列表中删除会导致列表迭代我的对象并对它们进行比较(调用 .Equals) - 这就是导致我的 ClientObject 再次尝试通信并因此引发异常的原因.

为了解决这个问题,我改为将列表更改为一个字典,该字典以我的客户端在连接到服务器时提供的唯一 ID 为关键字。然后我使用该唯一 ID 删除客户端。

除了捕获错误之外,我从未找到直接确定客户端是否断开连接的方法。

【问题讨论】:

    标签: c# asp.net remoting


    【解决方案1】:

    不确定#2。但是,如果您尝试从 foreach 循环内部的 clientList 中删除项目,则不能。这是 .NET 规则——在枚举对象时不要更改它的内容。

    相反,如果您在 foreach 循环中发现错误,请将其存储在另一个列表(“断开连接”列表)中。在 foreach 之后,从 clientList 中删除所有断开连接的项目。

    【讨论】:

    • 谢谢,实际上我并没有在 For 循环期间将其从列表中删除。该错误与无法修改集合有关。当我执行 clientList.Remove(badClient) 时,它会抛出“Connection denied”异常......这看起来很奇怪,但似乎只是通过引用“badClient”它试图使用该对象与客户端进行通信。
    • 什么是clientList——一个List? Remove 方法首先执行 IndexOf 以查看您传入的对象是否实际存在于集合中。在幕后,IndexOf 可能会调用对象的 Equals 运算符,也可能调用 GetHashCode()。这些调用中的任何一个都将通过网络发送 - 从而导致额外的通信异常。
    • 是的,它是一个 List - 那是有道理的。
    猜你喜欢
    • 2012-10-27
    • 2015-05-01
    • 2016-02-25
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多