我已经跟随Tomek Janczuk的使用HTTP轮询双工WCF通道的发布/订阅示例,但我注意到当客户端关闭浏览器断开连接时,服务在下一次回调时没有发现。 我本来期望会出现异常或类似的东西,以表示终结点不再存在。
如何知道客户端已经离开,以便停止向该客户端发布?
如何知道客户端已经离开,以便停止向该客户端发布?
确切的说: 不可能。
当TCP连接被关闭时(作为HTTP调用的基础),会向服务器发送一条特殊的TCP消息-FIN数据包。虽然HTTP是无状态的,但基础的TCP连接是有状态的,并且通过保持活动状态,底层的TCP连接通常保持打开状态。如果客户端被处理,TCP连接将被关闭并通常向服务器发送一条消息。但是,如果它崩溃或其网络断开连接,则它将没有时间执行此操作。所以总之,你永远无法确定。
这里 了解更多信息。
由于受限的SL双工功能,这几乎是不可能的。我们在服务中实现了用户列表,并添加了“IsDisconnected”和“LastCommunicationTime”属性。当WCF服务尝试向用户的传出消息队列中添加消息时,如果超时并失败,会抛出超时异常。我们将“IsDisconnected”标记为true,并在下次不再尝试向该用户发送消息。
另一个线程一直监视着这个情况,如果它注意到“LastCommunicationTime”已经超过了一定时间,并且“IsDisconnected”为true,则会将该用户从列表中移除,除非同一用户在此期间内再次尝试连接(我们通过其UserId来识别)。
由于这个问题使WCF服务非常繁忙,因此我们手动处理了很多事情。
new Thread(new ThreadStart(() =>
{
while (SilverlightClients != null)
{
lock (SilverlightClients)
{
SilverlightClients = SilverlightClients.Where(d => (d.Callback as IContextChannel).State != CommunicationState.Opened).ToList();
}
Thread.Sleep(1000);
}
})) { Name = "Thread Remove Disconnected Clients" }.Start();