如何从服务器向客户端发送更新?

5
我正在构建一个C#/WPF项目。 它的架构如下:
  • 控制台应用程序将位于虚拟机(或我的家用电脑)上,作为服务器端。
  • WPF应用程序将是客户端应用程序。
现在我的问题是这样的——我希望服务器能够向客户端发送更改。例如,如果我有一个针对客户端ABC的更改,我希望服务器知道如何调用客户端计算机上的服务。 问题是,我不知道服务器将如何调用客户端。
举个小例子,以防我没有解释清楚: 服务器在计算机1上,有两个客户端,分别在计算机2和3上。 客户端2有一辆丰田汽车,客户端3有一辆宝马汽车。 计算机1上的服务器想要告诉客户端2,它有一辆新车,一个复仇者。
我该如何跟踪并调用客户端上的服务? 我考虑将他们的IP地址(从cmd中调用ipconfig)保存在数据库中——但这不是基于他们连接的WI-FI/网络吗?
感谢任何帮助!

如果我说错了,有人可以纠正我,但客户应该询问是否有更新。这并不完全是服务器的工作。 - Broots Waymb
你在使用什么框架进行服务器/客户端连接?WCF?你考虑过使用类似Azure事件中心的东西吗? - Dan Field
4个回答

7

你可以尝试实现 SignalR。这是一个很棒的库,它使用WebSockets将数据推送到客户端。

编辑:

SignalR可以帮助您通过允许在控制台应用程序(服务器)上设置Hub,使WPF应用程序(客户端)连接到该Hub来解决您的问题。当客户端启动时,您将使用指定的Hub注册它们。当服务器上发生更改时,您可以从服务器Hub向客户端推送。客户端将从服务器接收信息,并允许您根据需要处理它。

一些代码的粗略模拟:

namespace Server{}
    public class YourHub : Hub {
        public void SomeHubMethod(string userName) { 
            //clientMethodToCall is a method in the WPF application that
            //will be called. Client needs to be registered to hub first.
            Clients.User(userName).clientMethodToCall("This is a test.");
        
           //One issue you may face is mapping client connections.
           //There are a couple different ways/methodologies to do this.
           //Just figure what will work best for you.
         }
    }
}

namespace Client{
    public class HubService{          
      
      public IHubProxy CreateHubProxy(){
          var hubConnection = new HubConnection("http://serverAddress:serverPort/");
          IHubProxy yourHubProxy = hubConnection.CreateHubProxy("YourHub");
          return yourHubProxy;
        }
    }

}

然后在你的 WPF 窗口中:

var hubService = new HubService();
var yourHubProxy = hubService.CreateHubProxy();
yourHubProxy.Start().Wait();
yourHubProxy.On("clientMethodToCall", () => DoSometingWithServerData());

如果您能解释一下SignalR如何满足这种架构需求,那么这将是一个更有帮助的答案。 - Dan Field

2
你需要为客户端创建某种订阅模式,以便服务器处理发布-订阅频道(参见http://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html)。基本架构如下:
  1. 客户端向消息通道发送请求,将自身注册为某种消息/事件等的订阅者。
  2. 服务器向通道发送消息,以便将其传递给订阅该消息的订阅者。
有很多方法可以处理这个问题。如果你不想重复发明轮子,可以使用一些 Azure 服务(例如事件中心或主题)。你也可以让服务器应用程序跟踪所有这些事情(更新 IP 地址、更新订阅兴趣、确保消息不会被发送超过一次;确保消息持久性 [即使在客户端离线时也能确保消息被传送])。

2
通常,无论您选择哪种解决方案,都会面临一个共同问题 - 客户端隐藏在防火墙后面并具有动态IP地址。这使得服务器向客户端推送变得困难(我听说过一些声称可以克服这个问题的技术,但没有看到实际应用)。实际上,客户端发言,服务器倾听并响应。但是,您可以使用以下方法来模拟推送: 1.轮询(客户端定期请求信息) 2.长轮询(客户端请求信息,服务器保持请求直到信息到达或超时) 3.套接字(客户端请求服务器连接,该连接用于双向通信一段时间)。
了解这些术语后,您的下一个选择是编写自己的代码或使用第三方服务(Azure,Amazon或其他)为您传递消息。我个人喜欢长轮询,因为它易于实现。在我的应用程序中,我有以下设置。
- 在Azure上运行Web API服务器,其中包含一个侦听消息请求的端点。 - 服务器代码内部的简单循环,每100毫秒检查新消息是否存在于数据库中。 - 调用API的客户端处理响应。
如上所述,有许多方法可以做到这一点。在您的特定情况下,一种方法如下。
1.客户端A调用服务器API以侦听消息。 2.服务器保持呼叫,等待数据库中的新消息条目。 3.客户端B调用服务器API以发布新消息。 4.服务器将消息保存到数据库中。 5.来自步骤2的服务器实例看到新消息。 6.服务器将消息返回给客户端A。
此外,消息不一定要存储在数据库中 - 这取决于您的需求。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接