Asp.net SignalR application and implementation of the group chat function open source code, asp. netsignalr
ASP. NET SignalR is a library provided by ASP. NET developers. It simplifies the process for developers to add real-time Web functions to applications. The real-time Web function refers to a function that allows the server code to push content immediately when the connected client becomes available, rather than waiting for the server to wait for the client to request new data. (From the official introduction .)
Official website of SignalR
-1. Reasons for writing this article
In the previous article, SignalR is not described in detail in the real-time communication solution of B/S (Web). Therefore, another article specifically introduces SignalR, which focuses on the Hub function.
0. First view the final effect
1 public class Startup2 {3 public void Configuration (IAppBuilder app) 4 {5 app. MapSignalR (); 6} 7}
Configure the Startup class in web. config, and add
<Add key = "owin: AppStartup" value = "SignalRChat. App_Start.Startup"/>
1.2.2 introduce SignalR js on the page
1. Because the front-end of SignalR is based on jQuery, jQuery must be introduced to the page.
2. Introduce the js of SignalR.
3. Introduce the most important hubs js. This js does not actually exist. SignalR will reflect and obtain all the methods called by the client and put them in hubs js.
<script src="~/Scripts/jquery-1.10.2.js"></script><script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script> <script src="~/signalr/hubs"></script>
1.2.3 create a GroupChatHub class and inherit the Hub abstract class
The method in the hub class is the js method provided to the client.
In js, you can use signalr to call SendMsg.
[HubName("simpleHub")] public class SimpleHub : Hub { public void SendMsg(string msg) { } }
In this way, the preparatory work is basically completed, and the specific operation is later.
2. Principles and simple programming
In fact, it is very easy to understand the principle. Because http is stateless, every request will be disconnected from the server, which means that the client can easily find the server, however, it is troublesome for the server to send messages to your client. If you do not understand, refer to the previous article B/S (Web) Real-time communication solution.
SignalR can solve this problem very well.Full Duplex Communication Between the browser and the server.
2.1 Client to server (B => S)
Client code
<Script type = "text/javascript"> var ticker = $. connection. simpleHub; $. connection. hub. start (); $ ("# btn "). click (function () {// After the link is complete, you can send the message to the server ticker. server. sendMsg ("message to be sent") ;}); </script>
Server code
[HubName ("simpleHub")] public class SimpleHub: Hub {public void SendMsg (string msg) {// obtain the link id var connectionId = Context. connectionId; // obtain the cookie var cookie = Context. requestCookies ;}}
WhereSimpleHubIs the inheritance we defineHubClassSimpleHubThen we can rename it with the HubName feature.
Then start the link.
After the link is complete, we can callSimpleHubClass. This makes it easy to send messages from the client to the server.
[HubName ("simpleHub")] public class SimpleHub: Hub {public void SendMsg (string msg) {Clients. All. msg ("message sent to client ");}}
Client code
<script type="text/javascript"> var ticker = $.connection.groupChatHub; $.connection.hub.start(); ticker.client.msg = function (data) { console.log(data); } </script>
It demonstrates how to send a message to the client, which is also an important function of SignalR. There are two problems to solve here.
Problem 1: the message is sent to all connected clients.SingleClient orBatchHow should the client send the message.
Problem 2: when calling msg to send a message to a client, we receive the feedback after receiving the message and then send the message to the client. This is similar.AjaxThe server did not send messages to the client.
Solution:
Question 1: Clients can send messages to a group of features or a client.
// All Clients. all. msg ("messages sent to the client"); // specific cooectionId Clients. client ("connectionId "). msg ("messages sent to Clients"); // specific group Clients. group ("groupName "). msg ("messages sent to clients ");
This is commonly used. Of course there are many more, such as AllExcept and Clients.
Added Others, OthersInGroup, OthersInGroups and so on in SignalR2.0.
Problem 2: You can call GlobalHost. ConnectionManager. GetHubContext <SimpleHub> (). Clients to obtain the Clients in the message to be sent. We 'd better write itSingleton ModeBecause this requirement is in line with the Singleton, the group chat has detailed code.
3. Implement group chat using SignalR
The above introduction and code can already implement B => s and s => B, so it is easier to implement group chat and separate chat.
Because the function is relatively simple, I save the user name to the cookie, that is, the cookie needs to be set when I first come in.
In addition, it must be implemented in the hub.OnConnected,OnDisconnectedAndOnReconnectedAnd then set the user and connectionid andCount online usersFor chat purposes.
Hub code
/// <Summary> /// SignalR Hub group chat class // </summary> [HubName ("groupChatHub")] // mark the name for js to call public class GroupChatHub: hub {// <summary> /// user name /// </summary> private string UserName {get {var userName = Context. requestCookies ["USERNAME"]; return userName = null? "": HttpUtility. urlDecode (userName. value) ;}/// <summary> /// online user /// </summary> private static Dictionary <string, int> _ onlineUser = new Dictionary <string, int> (); // <summary> // start connection // </summary> // <returns> </returns> public override Task OnConnected () {Connected (); return base. onConnected () ;}/// <summary >/// relink /// </summary> /// <returns> </returns> public override Task OnReco Nnected () {Connected (); return base. OnReconnected ();} private void Connected () {// process online staff if (! _ OnlineUser. containsKey (UserName) // if the name does not exist, it is a new user {// Add online employee _ onlineUser. add (UserName, 1); // send online personnel Clients to the client. all. publshUser (_ onlineUser. select (I => I. key); // send the client to add the chat message Clients. all. publshMsg (FormatMsg ("system message", UserName + "join chat");} else {// if the user already exists, add the number of online connections + 1 _ onlineUser [UserName] = _ onlineUser [UserName] + 1;} // to the Hub Group to send a separate Message Groups. add (Context. connectionId, "GROUP-" + UserName );} /// <summary> /// end connection /// </summary> /// <param name = "stopCalled"> </param> /// <returns> </returns> public override Task OnDisconnected (bool stopCalled) {// Number of people links-1 _ onlineUser [UserName] = _ onlineUser [UserName]-1; // determine whether all links are disconnected. if (_ onlineUser [UserName] = 0) {// remove the online operator _ onlineUser. remove (UserName); // send online personnel Clients to the client. all. publshUser (_ onlineUser. select (I => I. key); // send the Clients to the client to exit the chat. all. publshMsg (FormatMsg ("system message", UserName + "quit chat");} // remove the Hub Group Groups. remove (Context. connectionId, "GROUP-" + UserName); return base. onDisconnected (stopCalled);} // <summary> // send a message, for the client to call // </summary> /// <param name = "user"> user name. If it is 0, the message is sent to the owner </param> /// <param name = "msg"> message </param> public void SendMsg (string user, string msg) {if (user = "0") {// send the client message to all users. all. publshMsg (FormatMsg (UserName, msg);} else {// send to your own message // Clients. group ("GROUP-" + UserName ). publshMsg (FormatMsg (UserName, msg); // send it to the selected personnel // Clients. group ("GROUP-" + user ). publshMsg (FormatMsg (UserName, msg); // send it to your own message Clients. groups (new List <string> {"GROUP-" + UserName, "GROUP-" + user }). publshMsg (FormatMsg (UserName, msg ));}} /// <summary> /// format the message to be sent /// </summary> /// <param name = "name"> </param> /// <param name = "msg"> </param> // <returns> </returns> private dynamic FormatMsg (string name, string msg) {return new {Name = name, Msg = HttpUtility. htmlEncode (msg), Time = DateTime. now. toString ("yyyy-MM-dd HH: mm: ss ")};}}
Js Code
<Script type = "text/javascript"> $ (function () {// link hub var ticker = $. connection. groupChatHub; $. connection. hub. start (); // receives the message sent by the server $. extend (ticker. client, {// receives the chat message publshMsg: function (data) {$ ("# msg "). append ("<li> <span class = 'P'>" + data. name + ": </span>" + data. msg + "<span class = 'time'>" + data. time + "</span> </li>") $ ("# msg "). parents ("div") [0]. scrollTop = $ ("# msg "). parents ("div") [0]. ScrollHeight;}, // receives online staff, and then joins the Select statement for separate chat to Select publshUser: function (data) {$ ("# count "). text (data. length); $ ("# users "). empty (); $ ("# users "). append ('<option value = "0"> all </option>'); for (var I = 0; I <data. length; I ++) {$ ("# users "). append ('<option value = "' + data [I] + '">' + data [I] + '</option> ')}}}); // send message button $ ("# btn-send "). click (function () {var msg = $ ("# txt-msg "). val (); if (! Msg) {alert ('enter the content! '); Return false ;}$ ("# txt-msg"). val (''); // actively sends the message, sends it to, and sends the content. Ticker. server. sendMsg ($ ("# users"). val (), msg) ;}); </script>
Html code
<H2> group chat system (<span id = "count"> 1 </span> online): @ ViewBag. userName
In this way, the group chat function is sent to a specific user.
3.1. encapsulation of a single example that actively sends messages
/// <Summary> /// actively send the message to the user. Singleton mode // </summary> public class GroupChat {/// <summary> // Clients, used to actively send messages // </summary> private IHubConnectionContext <dynamic> Clients {get; set;} private readonly static GroupChat _ instance = new GroupChat (GlobalHost. connectionManager. getHubContext <GroupChatHub> (). clients); private GroupChat (IHubConnectionContext <dynamic> clients) {Clients = clients;} public static GroupChat Instance {get {return _ instance ;}} /// <summary> /// actively send messages to everyone, the system directly calls /// </summary> /// <param name = "msg"> </param> public void SendSystemMsg (string msg) {Clients. all. publshMsg (new {Name = "system message", Msg = msg, Time = DateTime. now. toString ("yyyy-MM-dd HH: mm: ss ")});}}
To send a message, call SendSystemMsg directly.
GroupChat. Instance. SendSystemMsg ("message ");
4. Conclusion
Let's talk about the source code.
Github: https://github.com/Emrys5/SignalRGroupChatDemo
Online Demo: http://chat.lining.name/
I hope it will be helpful to you. This article is original and you are welcome to make a brick andRecommendation.