20

我正在为远程仪器创建 Silverlight 2 用户界面。不同站点的两个并发用户与仪器交互(仪器操作员和远程科学家)和任意数量的观察者用户不与其交互,只是观看。但是,每当两个活动用户中的一个更改某些内容时,这些更改必须立即反映在所有用户的 UI 中,例如平移或缩放图像或注释或选择图像的一部分,将项目添加到显示在列表框中的集合中。在客户端中,我使用可观察的集合,这些集合很容易反映该用户所做的更改,但很难看到另一个用户所做的更改。我可以轮询每个客户端的更改,但推送通知之类的东西会更好。我已经广泛搜索了示例,但没有找到任何我需要的东西。Silverlight 与 WCF 服务交互时存在各种安全问题,这意味着许多潜在示例无法正常工作。我在这个项目上基本上没有时间了,需要快速帮助。有没有人建议一个合适的简单例子来说明如何做到这一点?我是一位经验丰富的开发人员,但必须自学 Silverlight 和 WCF 服务,而我所在地区没有人知道这些。即使我已经完成了大量的 ASP.NET 工作,我也不是 Web/Javascript 专家。谢谢。我在这个项目上基本上没有时间了,需要快速帮助。有没有人建议一个合适的简单例子来说明如何做到这一点?我是一位经验丰富的开发人员,但必须自学 Silverlight 和 WCF 服务,而我所在地区没有人知道这些。即使我已经完成了大量的 ASP.NET 工作,我也不是 Web/Javascript 专家。谢谢。我在这个项目上基本上没有时间了,需要快速帮助。有没有人建议一个合适的简单例子来说明如何做到这一点?我是一位经验丰富的开发人员,但必须自学 Silverlight 和 WCF 服务,而我所在地区没有人知道这些。即使我已经完成了大量的 ASP.NET 工作,我也不是 Web/Javascript 专家。谢谢。

4

8 回答 8

10

Silverlight 2 使用新的 WCF PollingDuplexHttpBinding 支持支持推送通知。Silverlight SDK 安装了两个程序集(一个用于 Silverlight 应用程序,一个用于 WCF 服务器)。

我有一些博客文章和一个完整的示例应用程序,它们演示了如何从控制台应用程序服务器“推送”股票更新,该控制台应用程序服务器自托管 WCF 服务到连接的客户端。它还展示了每个客户端如何针对股票添加注释并将这些注释同步(从服务器推送)到所有其他连接的客户端。

示例的最新版本(第 4 部分)展示了如何使用两个服务器端点在 Silverlight 和 WPF 客户端之间同步推送更新,如下所示:

using System;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace StockServer
{
    public class StockServiceHost : ServiceHost
    {
        public StockServiceHost(object singletonInstance, params Uri[] baseAddresses)
            : base(singletonInstance, baseAddresses)
        {
        }

        public StockServiceHost(Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
        }

        protected override void InitializeRuntime()
        {
            this.AddServiceEndpoint(
                typeof(IPolicyProvider),
                new WebHttpBinding(),
                new Uri("http://localhost:10201/")).Behaviors.Add(new WebHttpBehavior());

            this.AddServiceEndpoint(
                typeof(IStockService),
                new PollingDuplexHttpBinding(),
                new Uri("http://localhost:10201/SilverlightStockService"));

            this.AddServiceEndpoint(
                typeof(IStockService),
                new WSDualHttpBinding(WSDualHttpSecurityMode.None),
                new Uri("http://localhost:10201/WpfStockService"));

            base.InitializeRuntime();
        }
    }
}

WPF 客户端连接到 WSDualHttpBinding 端点,Silverlight 客户端连接到同一 WCF 服务的 PollingDuplexHttpBinding 端点。该应用程序还展示了如何处理 Silverlight 客户端访问策略要求。

客户端(Silverlight 或 WPF)可以在其 UI 中针对股票添加注释,这些注释传播回服务器以推送到所有其他客户端。这演示了双向通信,并有望执行您的应用程序所需的所有必要通信。

您可以在此处查看运行的演示应用程序的屏幕截图。

于 2009-03-12T21:57:59.117 回答
6

这并不是在以粉丝男孩的方式推动 Flex,但事实上,这是我们在所有基于 Flex 的应用程序中经常构建的那种架构。这是我们在 Flex 上所做的 - 毫无疑问,它可以适当地转换为 Silverlight:

我们采用三种成分并将它们整合在一起以实现此功能:

  1. Comet 模式(一种与 HTTP 兼容的服务器推送通知方式 - 查看 Wikipedia 了解更多信息)
  2. JMS 消息传递主题(发布/订阅者队列)
  3. Adobe BlazeDS servlet

后一项实现了 Comet 模式,支持 AMF 对象编组(Adobe 的 ActionScript3 对象的二进制序列化格式),并桥接到 JMS 队列或主题。当桥接到一个主题时,在浏览器中运行的多个 Flex 客户端可以作为 JMS 主题的订阅者进行代理。因此,如果任何客户端发布消息(或服务器端代码发布到主题中),所有客户端订阅者都将通过 BlazeDS 和彗星模式实现将消息推送给他们。

实际上,您需要找到或编写一个完成 BlazeDS 功能的组件。您可能还需要实现一些与此服务器端组件的 Comet 模式交互的客户端代码。

WCF 是否支持彗星模式和双向消息传递?特别是在符合 HTTP 和端口 80 或端口 443 的 SSL 的情况下。看起来您已经对此进行了调查,但没有找到任何双向消息传递。因此,您可能需要卷起袖子并进行一些编码。

关于将服务器推送到 Web 应用程序的一些注意事项:

BlazeDS 支持实现 Comet 模式的两种主要模式(实际上有第 3 个轮询选项,但我忽略了它):

  1. 长轮询
  2. HTTP 流式传输

您应该会发现大多数 Web 浏览器更普遍支持长轮询。因此,您可能会简化为最初仅支持它。或者您可以花时间让您的客户端代码首先尝试 HTTP 流式传输,并在必要时切换到长轮询。

至于可以提供发布/订阅功能的消息代理,您可以考虑使用 ActiveMQ JMS。它是开源和免费的,有积极的社区支持(你也可以购买支持)。此外,您还可以使用 NMS 作为 .NET 客户端进行集成。

将消息代理放在中间层实际上很重要,因为它将是安全放置消息的地方。如果您的客户正在进行长轮询,您不希望他们在没有实际连接的时间间隔内错过任何新消息。

在高流量场景(数百或数千个客户端,例如 Internet 上的网站)中要考虑的另一件事是,您需要有一种可扩展的彗星模式方法。

在 Flex/Java 世界中,BlazeDS servlet(它是开源的)已被修改为使用异步模型。在 Java 中,可以构建套接字侦听器以使用 NIO 通道和 Java 并发执行器线程池。Tomcat Web 服务器有一个 NIO 监听器并支持异步 Servlet 3.0 事件。但是,特别是 BlazeDS 已经过修改,可以与 Jetty Web 服务器一起使用。底线是这种异步方法的可扩展性意味着单个物理 Web 服务器可以被增强以支持多达 20,000 个并发 Comet 式客户端连接。

自从我进行认真的 .NET 编程以来已经有一段时间了,但习惯了 io 功能很像 Java 1.1,除了具有异步结果处理程序功能。但是,这与通过 Java NIO 通道创建异步套接字侦听器不同。一个 NIO 通道实现可以用一个相对较小的线程池支持数百到数千个套接字连接。但是 C# 和 .NET 已经经历了两到三个重要的改进——也许已经添加了新的 io 功能,可以与 NIO 通道相媲美。

于 2009-03-12T21:43:23.270 回答
3

我只是想澄清一下 PollingDuplexHttpBinding 没有实现“真正的”推送通知,正如它的名称(轮询)所示。从msdn 文档

使用此绑定配置后,Silverlight 客户端会定期轮询网络层上的服务,并检查服务想要在回调通道上发送的任何新消息。服务对客户端回调通道上发送的所有消息进行排队,并在客户端轮询服务时将它们传递给客户端。

然而,它比传统的轮询 Web 服务的方式更有效,因为每次轮询后,服务器都会保持通道打开一段时间(比如 1 分钟),如果在这段时间内有消息到达,它将直接“推送” '给客户的消息。客户端必须反复更新其连接,也就是说轮询服务。

If you want to implement real push notifications with silverlight I believe you need to work with sockets, and I recommend reading some of Dan Wahlin's blog posts on the subject.

于 2009-09-02T15:36:41.903 回答
2

或者,

如果您想要一个不涉及代理、网桥或网络服务器的原生 silverlight API,您可以使用 my-Channels 中的 Nirvana 作为您的消息传递中间件。从 my-Channels 及其展示网站查看 Nirvana。(对不起,我是新用户,无法提交链接):

亚历克斯

于 2009-05-19T12:49:52.347 回答
2

编辑:它实际上工作正常。我被闭包中的“隐藏变量”严重咬伤:(

我为 SL2 使用了 PollingDuplex,我认为它还没有准备好投入生产。

我的主要问题是它不会歧视同一台机器上的客户端。如果我运行 2 个客户端,那么其中一个将无法再轮询服务器并且会因超时而死。两个客户端的 SessionId 不同,但它只是在客户端被忽略。

同样,如果我杀死一个客户端然后创建一个新客户端,那么新客户端将在一段时间内从前一个客户端获取推送更新。

有没有人遇到过同样的问题,还是在 SL3 中修复了?

实际上,我运行了更多演示代码并意识到由于某种原因您必须指定 InstanceContextMode 和 InstanceMode 以便服务是基于会话的而不是单例的(据我所知)。我提取的简单演示代码中存在明显的性能问题。

不幸的是,这种行为没有记录在案。

于 2009-06-30T07:39:18.747 回答
1

我的组织发现 Silverlight 2.0/WCF 推送实施有点“没有为黄金时间做好准备”,至少对于我们计划使用它的目的而言。

我们最终选择了 XMPP/Jabber,因为它是一种结构更完善的野兽,您可以在 Silverlight 中相当容易地实现它,只需从 Internet 上获取一些资源即可。

我相信 Silverlight 3.0 将实现更新/更完善的推送实现,从我可以从公开可用的信息中得知。

于 2009-03-24T17:51:52.193 回答
0

PollingDuplexHttpBinding 可能是最优雅的方法。

一种可能较少涉及的替代方法是使用 Silverlight 客户端的 TCP 套接字。每当其中一个 Silverlight 客户端需要推送更新时,您可以向它发送一条 TCP 消息,其中包含它需要调用的 WCF 服务的名称或一些其他轻量级信息。

我将这种方法用于应用程序并且效果很好。

于 2009-03-12T22:26:50.360 回答
0

网站http://www.udaparts.com/document/Tutorial/slpush.htm提供了一种更简单、更强大的解决方案

于 2009-06-05T02:45:50.777 回答