在现代网络应用中,服务器与客户端之间的实时通信变得越来越重要。SignalR 是一种服务器端代码,它简化了将数据从服务器推送到客户端(不仅仅是浏览器客户端)的过程。SignalR 处理了所有复杂的工作,使得开发者能够轻松实现实时通信功能。
SignalR 的一个常见误解是它仅适用于 ASP.NET/Web 应用程序。但实际上,如引言中提到的,客户端可以是非浏览器,例如桌面应用程序。SignalR 在幕后主要尝试使用 Web Socket 协议来发送数据。Web Socket 是 HTML5 的一项新 API,它允许客户端和服务器之间的双向通信。如果存在兼容性问题,SignalR 会使用长轮询等其他协议作为替代。
SignalR 的测试应用程序使用 Hub 类来设置服务器。定义了一个 Hub,它暴露了一个方法,作为客户端发送消息的端点。服务器可以处理消息,并将响应发送回所有或部分客户端。
C# [HubName("TestHub")] public class TestHub : Hub { public void ProcessMessageFromClient(string message) { Console.WriteLine($" {message}"); // 处理客户端请求并发送响应 string newMessage = $": Client message back in upper case: {message.ToUpper()}"; Clients.All.ResponseToClientMessage(newMessage); } }
SignalR 允许指定应用程序接受的“源”。这是通过 CORS 配置设置的。CORS 是一种安全概念,允许来自不同域的端点相互交互。
C# public void Configuration(IAppBuilder app) { app.UseCors(CorsOptions.AllowAll); app.MapSignalR(); }
服务器使用 OWIN(Open Web Interface for .NET)设置。OWIN 定义了 .NET Web 服务器和 Web 应用程序之间的抽象层。这有助于在 IIS 之外的进程中自托管 Web 应用程序。
C# static void Main(string[] args) { string url = @"http://localhost:8080/"; using (WebApp.Start(url)) { Console.WriteLine("============ SERVER ============"); Console.WriteLine("Server running at {url}"); Console.WriteLine("Wait for clients message requests for server to respond OR"); Console.WriteLine("Type any message - it will be broadcast to all clients."); Console.WriteLine("================================"); // 服务器广播测试 IHubContext ctx = GlobalHost.ConnectionManager.GetHubContext(); string line = null; while ((line = Console.ReadLine()) != null) { string newMessage = $" {line}"; ctx.Clients.All.MessageFromServer(newMessage); } // 暂停以允许客户端接收 Console.ReadLine(); } }
在上述代码中,使用 IHubContext:服务器设置为有先前定义的 Hub 作为广播端点之一。服务器还设置为可以自行广播任何消息给所有客户端。
客户端设置为通过 Hub 使用 HubConnection & IHubProxy 与服务器通信(发送和接收消息)。客户端可以调用 Hub 中暴露的端点来发送消息。
C# static void Main(string[] args) { string url = @"http://localhost:8080/"; var connection = new HubConnection(url); IHubProxy _hub = connection.CreateHubProxy("TestHub"); connection.Start().Wait(); // 服务器端发起消息 _hub.On("MessageFromServer", x => Console.WriteLine(x)); _hub.On("ResponseToClientMessage", x => Console.WriteLine(x)); Console.WriteLine("============ CLIENT ============"); Console.WriteLine("Type any message - it will be sent as a request to server for a response."); Console.WriteLine("================================"); string line = null; while ((line = Console.ReadLine()) != null) { // 向服务器发送消息 _hub.Invoke("ProcessMessageFromClient", line).Wait(); } Console.Read(); }
通过上述设置,可以看到客户端与服务器之间的实时通信如下:
选择 SignalR 时需要考虑的事项:
SignalR 看起来很棒。但是,在使用它时,有一些事项需要了解:
它是一种连接技术 - 每个通过 SignalR 连接的客户端都在 Web 服务器上使用一个持久且专用的连接。SignalR 被认为是可扩展的,但在有大量客户端的情况下,了解有关连接、内存、CPU 等的查询也无妨。
需要设置一个有效的主机服务器,并在其上打开一个用于通信的端口。这可能取决于组织的安全性协议和批准。