在桌面应用程序中实现 SignalR






4.91/5 (54投票s)
在桌面应用程序中实现 SignalR 的分步演练
引言
那么,让我们从头开始,首先讨论什么是 SignalR。
SignalR 是一种新兴的微软技术,它使我们能够构建实时应用程序,客户端可以将数据推送到服务器,服务器可以将数据推送到所有客户端。
它与新的 HTML5 WebSockets API 配合使用,该 API 实现了客户端(桌面应用程序和浏览器)与服务器之间的双向通信。如果 WebSockets 不可用,它会在不更改任何代码的情况下优雅地回退到其他技术。它还基于 OWIN (Open Web Interface for .NET)。
这使得它在构建实时应用程序(如聊天应用程序、监控仪表板等)方面非常有用。
这篇博文的目的是展示我们如何在服务器和桌面应用程序之间实现这种实时通信。对于开始感到焦虑的人,请放心,这并不像听起来那么复杂。如果您按照以下步骤操作,您会发现这根本不是一项艰巨的任务。
让我们将解释分解为以下步骤
- 为服务器创建 SignalR Hub
- 创建连接到 SignalR Hub 的桌面应用程序
- 从客户端应用程序发送消息到服务器
- 从服务器发送消息到客户端
Using the Code
创建 SignalR Hub
在实现 SignalR 时,最重要的事情之一是理解它的核心是我们所说的“Hub”。这个 Hub 实现了服务器和客户端之间的通信。
在创建示例 Hub 之前,我们首先需要决定如何托管 Hub。在托管 SignalR Hub 时有多种选项,每种选项都有自己的优缺点。
我们可用的 Hub 托管选项包括
- 自托管
- IIS 托管
- Windows 服务托管
例如,如果您需要 Hub 始终保持开启状态,并且它可以在机器重启时自动重启,那么服务托管选项是一个不错的选择。
为了简化本文,我将使用自托管选项,并且我们将在一个简单的控制台应用程序中托管 SignalR Hub。
那么,让我们开始吧
- 打开 Visual Studio,并创建一个新的控制台应用程序
- 我们需要在此应用程序上安装一些 Nuget 包。您可以通过 GUI 完成此操作,或在程序包管理器控制台中运行以下命令
Install-Package Microsoft.AspNet.SignalR.SelfHost
Install-Package Microsoft.Owin.Cors
接下来,让我们创建 Hub 本身
- 创建一个新的
public
类,并将其命名为TestHub
- 让
TestHub
继承自Hub
- 您可以通过在类上添加一个
HubName
属性来为Hub
提供一个新名称,例如
[HubName("TestHub")]
目前,Hub 还没有任何功能,但让我们从看看在控制台应用程序启动时启动 Hub 是多么容易开始。
创建一个名为 Startup
的新类,或者您喜欢的任何名称,并向其添加以下代码
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
这只是简单地使 Hub 能够进行跨域通信,并为我们正确映射应用程序中的所有 SignalR Hub。
下一步是在应用程序的入口点添加调用,为我们创建一个新的 Hub,这可以通过以下代码轻松完成(请注意,以下代码中的 Startup
指的是我们刚刚创建的类)
static void Main(string[] args)
{
string url = @"https://:8080/";
using (WebApp.Start<startup>(url))
{
Console.WriteLine(string.Format("Server running at {0}", url));
Console.ReadLine();
}
}
这就是我们创建 SignalR Hub 所需要做的全部工作。
您可以通过运行应用程序并在浏览器中浏览到以下 URL 来测试一切是否按预期工作。如果它工作正常,您将看到一堆 SignalR 相关代码。
https://:8080/signalR/hubs
到目前为止,一切顺利吗?很简单,对吧? :)
现在让我们继续桌面应用程序。
创建桌面客户端
对于本文,我将使用另一个控制台应用程序,但您可以使用 Winforms、WPF 或您想要的任何东西,请记住本教程侧重于使桌面应用程序与 SignalR 协同工作。Web 应用程序也与 SignalR 配合得很好,但本文不涉及。
首先,我们需要在客户端项目中安装 SignalR 客户端 Nuget 包。与 Hub
一样,这可以通过 GUI 或程序包管理器控制台完成。控制台的命令如下所示
Install-Package Microsoft.AspNet.SignalR.Client
完成此操作后,我们需要创建一个到 HubConnection
的代理。这可以通过几行代码轻松完成
static void Main(string[] args)
{
IHubProxy _hub;
string url = @"https://:8080/";
var connection = new HubConnection(url);
_hub = connection.CreateHubProxy("TestHub");
connection.Start().Wait();
}
连接到 SignalR Hub 的全部内容就是这样。
请注意,在此阶段,应用程序将在连接建立后关闭,因为它没有任何东西使其保持运行。我们将在下一步改进这一点。
接下来,我们将处理服务器和客户端之间的实际通信。
从客户端发送消息
注意事项
在设置服务器和客户端之间的通信时,最重要的事情是理解 SignalR 大部分使用 dynamic
对象,因此拼写非常重要。不用担心非语法纳粹分子。我说的不是根据字典正确拼写单词,而只是在服务器和客户端上使用相同拼写的方法名。原因很快就会清楚。
为了简化本文,让我们在服务器上创建一个方法,该方法将接收一些 string
值,并在客户端中返回 string
的长度。
我承认,这并不是实时应用程序中最令人兴奋的事情,但请包容我。
首先,在客户端中,我们需要添加代码,该代码将调用 Hub
上的特定方法,这就是拼写变得重要的地方。因此,在客户端中,在 SignalR 连接打开的部分之后添加以下内容
string line = null;
while ((line = System.Console.ReadLine()) != null)
{
_hub.Invoke("DetermineLength", line).Wait();
}
请注意上面部分中的 DetermineLength
部分。SignalR 将尝试调用 TestHub
上具有**完全**相同名称和参数的方法,在本例中为 string
值。
那么,现在让我们通过添加以下代码在 TestHub
上创建将接收此发送数据的相应方法
public void DetermineLength(string message)
{
Console.WriteLine(message);
}
请注意,即使我们想要返回一些东西,此方法也具有 void
返回类型。
我们现在可以运行解决方案,并通过验证消息是否打印到服务器上的控制台来确保消息按预期到达 TestHub
。
如果您在控制台中看不到任何打印,请验证方法名是否拼写完全相同。
在我们验证了我们的消息正在被 Hub 接收和处理后,我们可以专注于与客户端应用程序进行通信。
从服务器发送消息
有多种方法可以与连接到 Hub 的客户端进行通信。我们可以只响应调用客户端,将数据发送到所有连接的客户端,甚至只发送给少数选定的客户端。我们可能会在以后的文章中深入探讨这个问题。然而,现在,我们将响应所有连接的客户端。
因此,让我们将字符串的长度连接到收到的消息,并回复客户端。将以下行添加到您的代码中
public void DetermineLength(string message)
{
Console.WriteLine(message);
string newMessage = string.Format(@"{0} has a length of: {1}", message, message.Length);
Clients.All.ReceiveLength(newMessage);
}
请注意上面代码中的 ReceiveLength
。SignalR 将尝试调用客户端上具有**完全**相同名称和参数的方法。
那么让我们回到我们的客户端应用程序,添加将接收此数据并对其进行处理的代码。
在我们的客户端应用程序中,添加以下代码
_hub.On("ReceiveLength", x => Console.WriteLine(x));
On
方法指定一个方法名和一个动作。因此,每当 SignalR Hub 向该方法发送消息时,该特定动作就会执行。在我们的示例中,它只会将消息及其长度打印到控制台。
瞧,我们成功了!使用 SignalR 进行双向通信。给你一颗金星!
我们现在甚至可以运行多个客户端应用程序,每个应用程序都会响应其他应用程序的输入。去吧,试试看。你知道你想要尝试的...
结论
在这篇文章中,我们看到了使用 SignalR 创建实时应用程序是多么简单。它是一种非常强大的技术,我们只是触及了表面,但希望这篇文章足以让您对 SignalR 及其潜在用途产生兴趣和兴奋。