内容简介:We explore SignalR server/client technologies to build chat applications for the web.In this day and age, software systems have an undeniable need for real-time communications. Thankfully despite the hurdles, there are severalLet's pick one of the most pop
We explore SignalR server/client technologies to build chat applications for the web.
In this day and age, software systems have an undeniable need for real-time communications. Thankfully despite the hurdles, there are several techniques to enable real-time communications and polished frameworks that do much of the heavy lifting for developers. However, it is 2020, and software isn't siloed to specific platforms. As developers try to bring on newer platforms/devices to connect in real time, flexibility is key for technology stacks.
Let's pick one of the most popular real-time communication frameworks to dig into — the beloved SignalR on top of ASP.NET Core. And just like every human for the past million years, let's use chat apps as our playground. In a way, chat applications are the "Hello world" examples to prove real-time actually works. But let's use some fun APIs and try to build the same app across variety of platforms to see how SignalR caters to modern cross-platform needs, starting with web clients. And a little sprinkle of some polished UI never hurt good ole chat apps. Let's go.
SignalR
SignalR facilitates adding real-time communication to web applications running on ASP.NET and connected clients across wide variety of platforms. While SignalR started years back with ASP.NET MVC, the latest reboot is called SignalR Core, which runs on ASP.NET Core and brings a ton of maturity. Developers benefit from SignalR providing a uniform API canvas for connection and client management, as well as scaling to handle increased traffic.
SignalR provides APIs for bidirectional remote procedure calls (RPCs) between server and client and abstracts away real-time communication complexities. This is, by far, the biggest benefit of bringing in SignalR to facilitate real time communications — shield developers from having to deal with network layer implementations. Given a specific server/client pair, SignalR expertly chooses the best transport mechanism for real-time exchanges. The most common techniques used are: WebSockets, Server-Sent Events and Long Polling, in order of gracious fall-back plans.
SignalR Back End
SignalR uses the concept of hubs on the server side — a literal hub in a hub-spoke model. The SignalR Hub works as an in-memory object on the server side that all clients connect up to for real time communications. The hub allows SignalR to send and receive messages across machine boundaries, thus allowing clients to call methods on the server and vice versa. In addition to method invocation across programming paradigms, hubs allows transport of named and strongly typed parameters. SignalR automatically provides object serialization/deserialization to aid the process.
Let's build a quick demo chat application with a SignalR backend. Yes, yet another chat app — but demonstrating quick developer tricks and taking the chat app cross-platform. First, we have to begin with our server-side SignalR Hub. We'll start with a new ASP.NET Core Web Application running on .NET Core 3.0 — you can do this in VS on Windows, VS Code, VS for Mac or plain old CLI commands. We'll define our ChatHub
on the server-side like below. If you envision having multiple hubs, it may make sense to organize them in a hubs folder:
using Microsoft.AspNetCore.SignalR; using System.Threading.Tasks; namespace SignalRChat.Hubs { public class ChatHub : Hub { public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); } } }
Essentially, we're defining a method called SendMessage()
on the server that all connected clients can call and send in parameter values. When invoked, this server-side method turns around and tries to call ReceiveMessage()
method on clients — in particular, every connected client through Clients.All.SendAsync()
. The client-side methods would need to be defined in each client across platforms. Next up is a little bit of configuration in the ASP.NET Core app's Startup.cs file - essentially adding a middleware to route appropriate requests to the SignalR Hub, like so:
using SignalRChat.Hubs; namespace SignalRChat { public class Startup { ... public void ConfigureServices(IServiceCollection services) { ... services.AddSignalR(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... app.UseEndpoints(endpoints => { ... endpoints.MapHub<ChatHub>("/chatHub"); }); } } }
Web Client
With our SignalR server side backend all squared up, we'll begin with clients across various platforms, starting with web. While the SignalR bits to power hubs server side is included in ASP.NET Core 3.0 shared framework, the client side packages need to be brought in manually. Sure NuGet packages can be brought into projects, but a smarter way is to use Library Manager to get the client side dependencies through Unpkg . This ensures the SignalR JS files are being delivered through the Unpkg Content Delivery Network (CDN) — close to anywhere in the world where your users may be. Two CLI commands do the trick, adding the dependencies and moving them into the static files repository:
dotnet tool install -g Microsoft.Web.LibraryManager.Cli libman install @microsoft/signalr@latest -p unpkg -d wwwroot/js/signalr --files dist/browser/signalr.js --files dist/browser/signalr.min.js
Once done, you should see the static dependencies brought in, as well as, a libman.json file which provides details of provider, packages and destination, like so:
{ "version": "1.0", "defaultProvider": "unpkg", "libraries": [ { "library": "@microsoft/signalr@latest", "destination": "wwwroot/js/signalr", "files": [ "dist/browser/signalr.js", "dist/browser/signalr.min.js" ] } ] }
Now, let's write some boilerplate code, like in the SignalR docs , to have some UI for our SignalR-powered chat frontend. We essentially need a couple of input controls for chat, and a list to show to display chat messages. This goes in the ASP.NET site's Index.cshtml file in Pages directory:
@page <div> <div> </div> <div> <div>User</div> <div><input type="text" id="userInput" /></div> </div> <div> <div>Message</div> <div><input type="text" id="messageInput" /></div> </div> <div> </div> <div> <div> <input type="button" id="sendButton" value="Send Message" /> </div> </div> </div> <div> <div> <hr /> </div> </div> <div> <div> <ul id="messagesList"></ul> </div> </div> <script src="~/js/signalr/dist/browser/signalr.js"></script> <script src="~/js/chat.js"></script>
And now we'll add the JavaScript code to power web clients to talk to our SignalR Hub. This could go in a chat.js file:
"use strict"; var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build(); document.getElementById("sendButton").disabled = true; connection.on("ReceiveMessage", function (user, message) { var msg = message.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); var encodedMsg = user + " says " + msg; var li = document.createElement("li"); li.textContent = encodedMsg; document.getElementById("messagesList").appendChild(li); }); connection.start().then(function () { document.getElementById("sendButton").disabled = false; }).catch(function (err) { return console.error(err.toString()); }); document.getElementById("sendButton").addEventListener("click", function (event) { var user = document.getElementById("userInput").value; var message = document.getElementById("messageInput").value; connection.invoke("SendMessage", user, message).catch(function (err) { return console.error(err.toString()); }); event.preventDefault(); });
The code above essentially does three basic things:
SendMessage() ReceiveMessage()
That's it for a basic chat application powered by SignalR on both server and client side. Let's fire up two browser instances of our local app — real time chat just works.
Connection Management
SignalR Hubs on the server side offer a plethora of APIs for connection management. Some really useful ones are:
- Hubs expose a context property that carries a wealth of information about connection with clients, including unique identifiers for each connection/user
- A clients property holds the collection of all connected clients and allows for fine tuned management
- SignalR Hubs can be strongly typed through hub
where client methods need to implement interfaces - SignalR Hubs raise events when clients connect/disconnect, as well as, having reconnect functionality for select client platforms
Since we started with a chat application, a common business scenario is to build a chatroom. Thankfully, SignalR Hubs offer granular control over how messages are distributed to connected clients. As clients connect up to the hub, they can be put into groups and messages can be streamed to the caller/everyone connected/named groups etc. Here's some sample code in our SignalR Hub:
public Task SendMessageToCaller(string message) { return Clients.Caller.SendAsync("ReceiveMessage", message); } public override async Task OnConnectedAsync() { await Groups.AddToGroupAsync(Context.ConnectionId, "ChatRoom"); await base.OnConnectedAsync(); } public override async Task OnDisconnectedAsync(Exception exception) { await Groups.RemoveFromGroupAsync(Context.ConnectionId, "ChatRoom"); await base.OnDisconnectedAsync(exception); } public Task SendMessageToGroup(string message) { return Clients.Group("ChatRoom").SendAsync("ReceiveMessage", message); }
The code above should be self-explanatory; we're simply grouping clients and sending messages selectively. Here's the result, after some UI cleanup:
Transport Configuration
One other interesting aspect of modern SignalR is configurability of network stack. As mentioned before, SignalR chooses the best possible fit for network transport given the server-client pair, gracefully switching between WebSockets, Server-Sent Events and Long Polling. For most modern web clients using evergreen browsers, the obvious transport choice is WebSockets. You get dependable bi-directional communication between client/server. Developers should never be in doubt as to what SignalR is doing under the covers with network transport. While most browser developer tools will show traffic patterns and content, sophisticated network proxies likeFiddlerprovide developers with even more ammunition to manipulate/test/record SignalR communications.
SignalR also has serialization/deserialization built-in, so that developers need not be constrained to passing strings back and forth. Full objects can be transported and flattened/hydrated across platform barriers. The most common way to pass around seriliazed data is JSON and SignalR is pre-configured to use JSON - the default is JSON serialization/deserialization built into .NET, but one can also switch to using NewtonSoft.Json. Even with WebSockets network, one can look under the covers to see human-readable JSON being sent across the wire, as seen in Chromium DevTools here:
Have performance and bandwidth concerns for passing too much data around for your SignalR app? MessagePack is a popular binary serialization format that is much more compact than JSON, and SignalR supports MessagePack with a tiny bit of configuration on server and client. Binary serialization, however, means that SignalR message content is no longer readable, unless the bytes are passed through a MessagePack parser. So developers lose a bit of transparency, but the app gains efficacy and performance.
To configure MessagePack usage in SignalR communications, developers need to pull in the Microsoft.AspNetCore.SignalR.Protocols.MessagePack NuGet package server-side and explicitly mention the MessagePack protocol when adding the SignalR Middleware, like so:
services.AddSignalR().AddMessagePackProtocol();
One can also customize how MessagePack formats data and simple attributes can define how objects are serialized. On the web client side, MessagePack support with SignalR is provided by the @microsoft/signalr-protocol-msgpack npm package, which can be brought in like so:
npm install @microsoft/signalr-protocol-msgpack
We're essentially referencing some Node modules, which can be linked or the corresponding JS files brought in directly into the web project, like below:
Once our dependencies are in place, we can initialize the use of MessagePack as our web client goes up to connect to the SignalR Hub on server, like so:
var connection = new signalR.HubConnectionBuilder() .withUrl("/chatHub") .withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()) .build();
With MessagePack protocol in use, we should see network traffic serialized in binary format - better performance through smaller byte packages for the win!
Conversational UI
Hello world chat applications are fun first steps for real time apps. More realistic real-time apps can help automate complex enterprise workflows and the chat backend could like be an intelligent chatbot. There are a plethora of fabulous bot frameworks to hook up your chat apps to — all with rich tooling and SDKs for most platforms. And SignalR is happy to be the abstraction developers love over network complexities.
One other thing developers may need when building real-world chat apps — yes, polished and performant UI. When your goal is to automate workflows intelligently and deliver value, building chat UI by hand is too laborious and time consuming. EnterConversational UI - modern UI components for chatbots across Telerik/Kendo UI technologies. With wide framework compatibility, polished chat UI with detailed documentation and flexible APIs, developers can be on their way to implementing natural chat conversational flow quickly.
For SignalR powered web clients, Conversational UI can be brought in for a wide variety of platforms: through Telerik UI for ASP.NETAjax/ MVC /Core or Kendo UI forjQuery/ Angular / React /Vue. And these being web apps, they do not need to constrained to desktop browsers. Developers can absolutely build mobile-first PWA apps with polished chat UI. Hallelujah. Check out some of the quick demos of what's possible with real time chat applications that can automate workflows:
Wrap-Up
Life happens in real time and information exchange should be the same way. Turns out, there are countless modern applications that don't just benefit, but actively depend on real-time communications to be functional. SignalR has tremendous promise as a framework that aids in building real-time apps. With a ton of configurability, SignalR Hubs are easy to set up server-side. And building web clients connected to SignalR Hubs is just as easy, with flexible APIs and wonderful abstraction of network complexities. So SignalR powered web apps are a done deal — easy peasy.
But could we stretch real-time apps to other platforms, like desktop or mobile? Yes, Absolutely. While we take on other platforms to support SignalR in subsequent articles, the web continues to enjoy ubiquity and real time apps grow to be more valuable each day. Developers and consumers rejoice.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
算法的陷阱
阿里尔•扎拉奇 (Ariel Ezrachi)、莫里斯•E. 斯图克 (Maurice E. Stucke) / 余潇 / 中信出版社 / 2018-5-1 / CNY 69.00
互联网的存在令追求物美价廉的消费者与来自世界各地的商品只有轻点几下鼠标的距离。这诚然是一个伟大的科技进步,但却也是一个发人深思的商业现象。本书中,作者扎拉奇与斯图克将引领我们对由应用程序支持的互联网商务做出更深入的检视。虽然从表面上看来,消费者确是互联网商务兴盛繁荣过程中的获益者,可精妙的算法与数据运算同样也改变了市场竞争的本质,并且这种改变也非总能带来积极意义。 首当其冲地,危机潜伏于计算......一起来看看 《算法的陷阱》 这本书的介绍吧!