【问题标题】:Investigating solutions for notifying WPF clients from server调查从服务器通知 WPF 客户端的解决方案
【发布时间】:2012-01-21 05:52:14
【问题描述】:

我有一个项目需要在服务器上发生某些事情时通知 WPF 桌面客户端。此外,不会广播到 WPF 客户端的通知(发送到每个客户端),它应该发送到特定的客户端。

我想远离老式的服务器轮询。这需要尽可能接近实时。

我以前从未有过此要求,我正在研究解决方案。我的第一个想法是使用SignalR.NET client。我还没有与 SignalR 合作过,但它似乎是一个解决方案。我知道这是对长轮询、服务器发送事件和 WebSockets 的抽象,具体取决于可用的内容。

我已经简要了解了带有回调和服务总线的 WCF,但对它们一无所知,也不知道这些技术是否适用于此。我可以使用以前解决过这个问题的人的一些反馈和建议。你会怎么做?

【问题讨论】:

  • 客户端和服务器之间的连接是在受控网络内,还是在“云”上?

标签: .net wpf client-server server-push signalr


【解决方案1】:

这个问题很有趣。

我们目前正在开发一个与多个 Web 服务交互的应用程序。其中一项要求是每个客户端都必须了解其他客户端所做的操作。

为了实现这一点,我们正在考虑创建一个 Web 服务,其目的只是构建一个要通知的客户端列表,并处理通知的对象、时间和通知内容背后的逻辑。客户端将在启动时向该服务注册。通知本身将使用您提到的回调来完成。

之所以使用完全独立的 Web 服务,是因为我们现有的所有服务都需要在每次调用时建立和断开连接。使用通知 Web 服务,只要客户端运行,就必须保持连接。

很抱歉,我无法提供更多帮助,因为我们正在自己开发这样的系统。我也有兴趣获得有关此主题的反馈。

【讨论】:

    【解决方案2】:

    这可以通过 WCF 和 duplex contracts 轻松完成。您可以定义客户端可以在服务器上执行的操作(如任何 Web 服务),此外,您可以定义服务器可以在客户端上执行的操作(即反向 Web 服务)。代码方面,它们都只是简单的方法调用。客户端具有调用服务器上操作的方法,它还必须提供一个实现回调合约的对象,这是一个服务器可以调用的接口,客户端必须提供一个实现。所有数据和消息的序列化/反序列化以及所有低级网络操作都由 WCF 处理,因此您不必担心。

    WCF 支持使用两个绑定(或“协议”)的双工合同:

    1. WSDualHttpBinding - 这需要两个基于 SOAP 的 HTTP 侦听器,一个在服务器上,一个在客户端上。当客户端想要联系服务器时,它会向服务器执行一个 HTTP 请求。当服务器想要联系客户端时,它会向客户端执行一个 HTTP 请求。这种方法的优点是任何网络连接都是短暂的,并且不会保持打开状态(与大多数 HTTP 连接一样),因此它可以支持大量或并发的客户端。主要缺点是它可能无法与 Internet 上的大多数客户端计算机一起使用,因为它们通常位于 NAT 之后(对于 Internet 上的服务器到服务器通信或 Intranet 或 LAN 内的任何类型的通信来说,这不是问题) .更多详情,请查看我的other answer

    2. NetTcpBinding - 这基本上打开了一个从客户端到服务器的套接字,并在会话期间保持打开状态。这甚至允许通过 NAT 进行双向通信,但由于连接必须保持打开状态,这对服务器来说有点负担,因此将能够支持较少的并发用户(但在大多数情况下可能仍然绰绰有余)。这是我在 WCF 上执行双工合同的首选方式,因为它更容易上手且更可靠。

    WCF 的优点是您可以在两个绑定之间切换而无需更改代码。所需要的只是更改配置(.config 文件)。

    无论您选择哪种方式,您都可以在两个方向上执行近乎即时的通信(当然,在网络延迟允许的情况下)。当您拥有如此丰富、强大且易于用户使用的框架(例如 WCF)时,我认为不需要 SignalR。如果您受限于在浏览器中运行,那么 SignalR 将是有意义的。由于您在 .NET 中运行,它只会引入不必要的摩擦。

    【讨论】:

    • 我将更多地研究 WCF 的这一领域,但我考虑 SignalR 的原因是因为我的经验是 WCF 引入了不必要的摩擦。
    【解决方案3】:

    您应该查看来自 Frozen Mountain 的 WebSync。我过去用过它,效果很好。它可以满足您的所有要求。他们甚至提供托管服务“WebSync on Demand”。 他们还提供免费产品(但最多 10 个并发用户)。 它是一种商业产品。如果您不想做所有的管道,WebSync 为您提供准备使用的 api,您可以开始使用并快速开始使用。 我听说过/读过 SignalR,还没有使用过,但 SignalR 似乎处于 alpha/beta 阶段,而 WebSync 非常成熟。

    【讨论】:

      【解决方案4】:

      您可以创建一个 wcf 服务,wpf 客户端在启动时将自己注册到其中。然后每个 wpf 可以与 msmq 或 rabbitmq 服务器通信,在那里他们将轮询基于客户端名称/唯一 ID 创建的自己的队列。在服务器端,您可以拥有一项服务,该服务将根据为每个客户端设置的条件将数据推送到队列中。

      【讨论】:

      • 您始终可以在每台运行 WPF 应用程序并从队列中读取的计算机上设置一个队列。只要您使用的是 WPF,您就需要轮询某些内容以获取数据,除非您使用 wcf 回调,这不如使用保留数据的队列可靠
      • 详细说明为什么它不那么可靠。
      • 它不可靠,因为您无法完全控制连接到您的服务的客户端。您将不得不编写大量代码来管理检测客户端的断开和连接,例如检查客户端连接是否出现故障。在客户端失去连接的情况下,他们将丢失在断开连接时发送的数据。如果您不介意丢失数据,这很好,但如果您想确保始终通知所有客户端,那么您需要一种方法来以某种方式保存数据。
      【解决方案5】:

      SignalR 等技术的重点是满足服务器和 Web 客户端之间实时通信的需求。他们利用 WebSockets 并回退到旧 Web 浏览器的旧/黑客通信机制。

      如果您的环境将是一个 LAN,而您的客户端是一个 .NET 应用程序,那么您可以使用一个 TCPServer 和多个 TCPClients。当您的 Web 服务器有更新/消息要发送时,告诉您的 TCPServer(可能通过将消息放在它正在侦听的消息总线上),这可以通知连接的客户端。实时网络技术是实现此目的的好方法,但这实际上取决于您当前的需求以及您对未来的计划:

      • 你想试试 SignalR - 如果是,那么它会起作用,你可能会玩得很开心。它也可能对未来的项目有用,并成为你弓上的一根好绳子。如果不是,则 TCPClient 和 TCPServer 方法可能会超级简单且执行速度更快。
      • 您是否需要其他类型的 Web 客户端将来能够接收通知? - 是的,SignalR 或其他更成熟的self hosted realtime web technology 可能是更好的解决方案。否 - TCPServer/Client
      • 您是否打算将数据分发到您的 LAN 之外? 是的 - 自托管选项或带有 .NET 库的hosted solution 事件可能是可行的方式,因为它们可以消除维护开销 (免责声明:我为Pusher 工作,他们提供这样的服务)。否 - 自托管或 TCPServer/Client。
      • 速度有多重要?如果它真的很重要,那么绝对没有开销的 TCP 连接将是最快的选择。第二个最佳选择是 WebSockets,然后是 HTTP 流,然后是 HTTP 长轮询。

      注意:虽然我说 TCPServer/Client 可能是最简单的方法,但我想强调它也可能不是。 WebSockets 是一项非常令人兴奋的技术,并且在许多方面比 TCPClient 技术更易于访问,因此可能成为任何服务器和客户端之间双向通信的主导技术*

      我无法对 Duplex Contracts 发表评论,但我的理解是它们建立的连接没有持久化,因此它们实际上是一种轮询解决方案 - 我可能错了。

      【讨论】:

      • 双工合约不使用轮询,至少对于框架提供的任何绑定(即您可以编写自己的自定义绑定来执行各种疯狂的事情)。
      • 他们用什么? HTTP 流式传输?
      • 啊,TCP - 用于 TCP 绑定 - 很明显。对于 HTTP,客户端实际上需要充当服务器,好吧,有一个 IP 地址,以便可以从服务器向它发出 HTTP 请求。
      【解决方案6】:

      我还在评估一种使用 pub/sub 服务将事件传达给 WPF 客户端的轻量级且简单的方法。我不需要保证消息传递,因此 MassTransit 或 NServiceBus 之类的解决方案似乎过于繁重,因为它们需要可用的队列(MSMQ 或其他)。我还要求该解决方案可作为 .NET 4.0 Client Profile 使用。

      在 WCF 上构建的一个似乎可行的解决方案是 nvents。我不确定该项目是否仍然有效。它易于使用,并且底层实现(WCF)被很好地抽象。无需繁琐的配置。

      我在 Per Brage 的 Blog 上遇到的另一个解决方案是使用带有反应式扩展的 SignalR。我没有尝试过他的实现,不确定它是否需要完整的配置文件,但值得阅读!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-27
        • 1970-01-01
        • 2017-01-16
        • 2023-03-16
        相关资源
        最近更新 更多