首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WCF -客户端回调与“保留订阅者列表”轮询

WCF -客户端回调与“保留订阅者列表”轮询
EN

Stack Overflow用户
提问于 2009-12-07 22:18:33
回答 4查看 5.5K关注 0票数 7

我想在WCF中创建一个简单的客户机-服务器示例。我做了一些回调测试,到目前为止还不错。我在下面的界面上玩了一会儿:

代码语言:javascript
运行
复制
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IStringCallback))]
public interface ISubscribeableService
{
    [OperationContract]
    void ExecuteStringCallBack(string value);

    [OperationContract]
    ServerInformation Subscribe(ClientInformation c);

    [OperationContract]
    ServerInformation Unsubscribe(ClientInformation c);
}

这是一个简单的例子。稍微调整了一下。您可以要求服务器“执行字符串回调”,在这种情况下,服务器会反转字符串并调用所有订阅的客户端回调。

现在,这里有一个问题:如果我想实现一个所有客户端都“注册”到服务器,并且服务器可以“询问”客户机是否还活着的系统,那么您会用回调(所以而不是这种“字符串回调”是一种TellTheClientThatIAmStillHereCallback)来实现这个系统吗?通过检查回调的通信状态,我还可以“知道”客户端是否死了。与此类似的是:

代码语言:javascript
运行
复制
Subscribers.ForEach(delegate(IStringCallback callback)
                    {
                        if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                        {
                            callback.StringCallbackFunction(new string(retVal));
                        }
                        else
                        {
                            Subscribers.Remove(callback);
                        }
                    });

我的问题,换句话说:

  • 服务器可能有3个客户端
  • 客户端A模(我拔掉笔记本电脑的插头)、
  • 服务器死掉并返回在线
  • 一个新客户端出现

F 211

因此,基本上,您是使用回调来验证客户端的“仍然存在状态”,还是使用轮询并跟踪“我没有听说客户端多久”.

EN

回答 4

Stack Overflow用户

发布于 2009-12-15 01:18:42

您可以通过ClosedClosingFaulted事件检测到连接状态的大多数更改。您可以在设置回调的同时将它们挂起。这肯定比投票好。

Faulted事件只会在您实际尝试使用回调(失败)之后触发。因此,如果客户端消失了--例如,硬重启或断电--那么您就不会立即收到通知。但你需要吗?如果是,为什么?

WCF回调在任何时候都可能失败,而且您总是需要将其保留在脑海中。即使客户机和服务器都很好,您也可能会因为异常或网络中断而出现故障通道。或者,在上次投票和当前操作之间的某个时候,客户端可能会离线。关键是,只要您以防御性的方式编写回调操作(这是一个很好的实践),那么对大多数设计来说,将上面的事件挂钩通常就足够了。如果由于任何原因发生错误--包括客户端无法响应-- Faulted事件将启动并运行您的清理代码。

这就是我所说的被动/懒惰方法,它比轮询或保持生存的方法需要更少的编码和网络聊天。

票数 3
EN

Stack Overflow用户

发布于 2010-03-07 02:52:23

如果您启用了可靠的会话,WCF在内部维护一个保持活动的控制机制。它通过隐藏的基础设施测试消息定期检查另一端是否还在。这些检查的时间间隔可以通过ReliableSession.InactivityTimeout属性受到影响。如果将属性设置为20秒,则在另一侧发生服务故障后大约20到30秒将引发ICommunicationObject.Faulted事件。

如果您希望确保客户端应用程序始终保持“自动连接”,即使在临时服务崩溃之后,您可能希望使用一个工作线程(来自线程池),该线程反复尝试在客户端创建一个新的代理实例,并在出现故障事件后调用会话启动操作。

作为第二种方法,由于您无论如何都是在实现工作线程机制,所以您也可能忽略错误事件,并在客户端应用程序的整个生命周期内让worker线程循环。您让线程反复检查代理状态,并在状态出现故障时尝试进行修复工作。

使用第一种或第二种方法,您可以实现服务总线体系结构(中介模式),确保所有客户端应用程序实例随时准备在服务运行时接收“自发”服务消息。

当然,只有当可靠的会话“本身”被正确地配置为一开始(使用具有会话能力的绑定,并以有意义的方式应用ServiceContractAttribute.SessionMode、ServiceBehaviorAttribute.InstanceContextMode、OperationContractAttribute.IsInitiating和OperationContractAttribute.IsTerminating属性)时,这才能工作。

票数 2
EN

Stack Overflow用户

发布于 2009-12-08 14:28:19

我也遇到过类似的情况,使用WCF和回调。我不想使用轮询,但我使用的是“可重传”协议,所以如果客户端死了,那么它就会挂起服务器,直到服务器超时并崩溃。

我不知道这是最正确还是最优雅的解决方案,但我所做的是在服务中创建一个类来表示客户端代理。该类的每个实例都包含对客户端代理的引用,每当服务器设置类的"message“属性时,就会执行回调函数。通过这样做,当客户端断开连接时,单个包装类将获得超时excetpion,并将自己从服务器的侦听器列表中删除,但是服务不必等待它。这实际上不能回答您关于确定客户端是否还活着的问题,但这是另一种构建服务以解决问题的方法。如果您需要知道客户端何时死亡,则可以在客户端包装器从侦听器列表中删除自身时进行提取。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1863318

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档