Signalr self host + MVC and other multi terminal message push services (I)

Time:2021-7-25

1、 Overview

Due to the needs of the project, there is a module function in the recent company project, which needs to be used to obtain the approval notice immediately; The original design scheme was to use ajax to conduct regular polling query on the server. At the beginning, when the amount of data and usage were small, it was OK. Later, with the increase of usage and the complexity of various businesses in the system, the pressure on the server became greater and greater. Therefore, I want to replace Ajax polling query with message push. When approval is submitted, I call the push method, Push the message to the next approver, which reduces the pressure on the server.

Signal is an HTML websocket framework running on. Net platform supported by Microsoft. Its main purpose is to enable the server to actively push messages to the client page, so that the client does not have to resend requests or use polling technology to obtain messages. Moreover, the compatibility of signalr is also very strong. I won’t talk about it here. Now that you have chosen signalr, let’s start!

My idea is to make signalr a self managed service and separate it from our B / s project. The benefits are: 1. The push service does not depend on IIS. Even if IIS hangs up, our push service can still run normally; 2. We can call this push service on multiple platforms, and multiple projects can be used at the same time;

2、 Create server

No more nonsense. I’m also the first time to write a blog. After introducing the business scenarios and ideas, let’s start rolling codes.

1. Create a solution called “signalrproject” with vs;

2. Create a new console named server under the signalrproject solution

3. In the package manager console, enter the following command


Install-Package Microsoft.AspNet.SignalR.SelfHost 

4. Enter the following command:


Install-Package Microsoft.Owin.Cors

5. Add the userinfo class in the server console. The code is as follows


using System; 
 
namespace Server 
{ 
 public class UserInfo 
 { 
  public string ConnectionId { get; set; } 
  public string UserName { get; set; } 
  public DateTime LastLoginTime { get; set; } 
 } 
}

6. Add the chathub class in the server console. The code is as follows

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Server
{
 [HubName("IMHub")]
 public class ChatHub : Hub
 {
  //Static properties
  public static List<UserInfo> OnlineUsers = new List<UserInfo>(); //  Online user list

  /// <summary>
  ///Login connection
  /// </summary>
  ///< param name = "userid" > userid < / param >
  ///< param name = "username" > username < / param >
  public void Register(string userName)
  {
   var connnectId = Context.ConnectionId;

   if (OnlineUsers.Count(x => x.ConnectionId == connnectId) == 0)
   {
    if (OnlineUsers.Any(x => x.UserName == userName))
    {
     var items = OnlineUsers.Where(x => x.UserName == userName).ToList();
     foreach (var item in items)
     {
      Clients.AllExcept(connnectId).onUserDisconnected(item.ConnectionId, item.UserName);
     }
     OnlineUsers.RemoveAll(x => x.UserName == userName);
    }

    //Add online people
    OnlineUsers.Add(new UserInfo
    {
     ConnectionId = connnectId,
     UserName = userName,
     LastLoginTime = DateTime.Now
    });
   }

   //All clients synchronize online users
   Clients.All.onConnected(connnectId, userName, OnlineUsers);
  }

  /// <summary>
  ///Send private chat
  /// </summary>
  ///< param name = "touserid" > receiver user connection ID < / param >
  ///< param name = "message" > content < / param >
  public void SendPrivateMessage(string toUserName, string message)
  {
   var fromConnectionId = Context.ConnectionId;

   var toUser = OnlineUsers.FirstOrDefault(x => x.UserName == toUserName);
   var fromUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == fromConnectionId);

   if (toUser != null )
   {
    Clients.Client(toUser.ConnectionId).receivePrivateMessage(fromUser.UserName, message);
    Clients.Client(toUser.ConnectionId).receivePrivateMessage(message);
   }
   else
   {
    //Indicates that the other party is not online
    Clients.Caller.absentSubscriber();
   }
  }

  public void Send(string name, string message)
  {
   //Clients.All { get; } //  On behalf of all clients
   //Clients.AllExcept(params string[] excludeConnectionIds); //  All clients except parameters
   //Clients.Client(string connectionId); //  Specific client, this method is the key to realize end-to-end chat
   //Clients.Clients(IList<string> connectionIds); //  Client in parameter
   //Clients.Group(string groupName, params string[] excludeConnectionIds); //  Specify the client group, which is also the key to group chat
   //Clients.Groups(IList<string> groupNames, params string[] excludeConnectionIds); Client group in parameter
   //Clients.User(string userId); //  Specific users
   //Clients.Users(IList<string> userIds); //  User in parameter

   Console.WriteLine("ConnectionId:{0}, InvokeMethod:{1}", Context.ConnectionId, "Send");
   Clients.All.addMessage(name, message);
  }

  /// <summary>
  ///Called on connection
  /// </summary>
  /// <returns></returns>
  public override Task OnConnected()
  {
   Console.writeline ("client connection, connection ID: {0}, current number of online people is {1}", context.connectionid, onlineusers. Count + 1);
   return base.OnConnected();
  }


  /// <summary>
  ///Called on disconnection
  /// </summary>
  /// <param name="stopCalled"></param>
  /// <returns></returns>
  public override Task OnDisconnected(bool stopCalled)
  {
   var user = OnlineUsers.FirstOrDefault(u => u.ConnectionId == Context.ConnectionId);

   //Judge whether the user exists, and delete if it exists
   if (user == null)
   {
    return base.OnDisconnected(stopCalled);
   }

   Clients.All.onUserDisconnected(user.ConnectionId, user.UserName); // Call client user offline notification
   //Delete user
   OnlineUsers.Remove(user);
   Console.writeline ("the client is disconnected, the connection ID is: {0}, the current number of online people is {1}", context.connectionid, onlineusers. Count);
   return base.OnDisconnected(stopCalled);
  }

  public override Task OnReconnected()
  {
   return base.OnReconnected();
  }
 }
}

7. Add the startup class in the server console. The code is as follows

using Microsoft.Owin.Cors;
using Owin;

namespace Server
{
 public class Startup
 {
  public void Configuration(IAppBuilder app)
  {
   //Allow CORS to cross domain
   app.UseCors(CorsOptions.AllowAll);
   app.MapSignalR();
  }
 }
}

8. Modify the program class added in the server console, and the code is as follows

using Microsoft.Owin.Hosting;
using System;

namespace Server
{
 class Program
 {
  static void Main(string[] args)
  {
   string url = " http://localhost:10086 ";// Set the external interface of signalr hub server
   Using (webapp. Start (URL)) // start signalr hub server
   {
    Console.WriteLine("Server running on {0}", url);
    Console.ReadLine();
   }
  }
 }
}

9. F5 runs

Then access in the browser http://localhost:10086/signalr/hubs

The results are as follows:

As shown in the figure above, the content is basically completed. Today, I’ll talk about it first. It’s getting late. I’ll take a break first, and then I’ll fill in the following articles when I have time

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support developpaer.

Recommended Today

Programming Xiaobai must understand the network principle

How is the network composed? Why can we easily surf the Internet now?Whether you are a computer major or not, you may always have such questions in your heart!And today we will solve this matter and tell you the real answer! Basic composition of network First, let’s look at this sentence Connect all computers together […]