【发布时间】: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 删除客户端。
除了捕获错误之外,我从未找到直接确定客户端是否断开连接的方法。
【问题讨论】: