web api使用SignalR

1.nuget安装 Microsoft.AspNetCore.SignalR

2.定义一个接口

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace SignalRCore.Hubs
{
    public interface IClient
    {
        /// <summary>
        /// 强类型中心
        /// </summary>
        /// <param name="user"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        Task ReceiveMessage(string user, string message);

        Task ReceiveMessage(ConcurrentDictionary<string, string> user, string message);

    }
}

3.创建SignalRHub类

using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace SignalRCore.Hubs
{
    public class SignalRHub : Hub<IClient>
    {

        private static ConcurrentDictionary<string, string> userIds = new ConcurrentDictionary<string, string>();
        
        /// <summary>
        /// 在所有连接的客户端上调用方法
        /// </summary>
        /// <param name="user"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        [HubMethodName("SendMessage")]
        public async Task SendMessage(string user, string message)
        {
            var Str = Context.ConnectionId;
            await Clients.All.ReceiveMessage(userIds, message);
        }

        /// <summary>
        /// 在调用集线器方法的客户端上调用方法
        /// </summary>
        /// <param name="user"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task SendMessageToCaller(string user, string message)
        {
            await Clients.Caller.ReceiveMessage(user, message);
        }

        /// <summary>
        /// 在所有连接的客户端上调用方法,但调用方法的客户端除外
        /// </summary>
        /// <param name="user"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task SendMessageToOthers(string user, string message)
        {
            await Clients.Others.ReceiveMessage(user, message);
        }

        /// <summary>
        /// 向组的所有客户端发送消息
        /// </summary>
        /// <param name="GroupName"></param>
        /// <param name="user"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task SendMessageToGroup(string GroupName, string user, string message)
        {
            //var item = Context.Items
            await Clients.Group(GroupName).ReceiveMessage(user, message);
        }

        /// <summary>
        /// 向指定用户发送消息
        /// </summary>
        /// <param name="user"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task SendMessageToUser(string user, string message)
        {
            var ConnectionId = Context.ConnectionId;
            var UserId = userIds.Where(x => x.Key != ConnectionId).FirstOrDefault().Key;
            await Clients.Client(UserId).ReceiveMessage(user, message);
        }

        /// <summary>
        /// 处理连接的事件
        /// </summary>
        /// <returns></returns>
        public override async Task OnConnectedAsync()
        {
            //Context.Items.Add()
            var Id = Guid.NewGuid().ToString();
            var ConnectionId = Context.ConnectionId;

            userIds.TryAdd(ConnectionId, Id);
            await base.OnConnectedAsync();
        }

        /// <summary>
        /// 断开连接
        /// </summary>
        /// <param name="exception"></param>
        /// <returns></returns>
        public override async Task OnDisconnectedAsync(Exception exception)
        {
            var ConnectionId = Context.ConnectionId;
            userIds.TryRemove(ConnectionId, out string outs);
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users");
            await base.OnDisconnectedAsync(exception);
        }


    }
}

4.注册服务

 

  //注入SignalR实时通讯,默认用json传输
            services.AddSignalR(options =>
            {
                //客户端发保持连接请求到服务端最长间隔,默认30秒,改成4分钟,网页需跟着设置connection.keepAliveIntervalInMilliseconds = 12e4;即2分钟
                options.ClientTimeoutInterval = TimeSpan.FromMinutes(4);
                //服务端发保持连接请求到客户端间隔,默认15秒,改成2分钟,网页需跟着设置connection.serverTimeoutInMilliseconds = 24e4;即4分钟
                options.KeepAliveInterval = TimeSpan.FromMinutes(2);
            });

 

这个解释一下,SignalR默认是用Json传输的,但是还有另外一种更短小精悍的传输方式MessagePack,用这个的话性能会稍微高点,但是需要另外引入一个DLL,JAVA端调用的话也是暂时不支持的。但是我其实是不需要这点性能的,所以我就用默认的json好了。另外有个概念,就是实时通信,其实是需要发“心跳包”的,就是双方都需要确定对方还在不在,若挂掉的话我好重连或者把你干掉啊,所以就有了两个参数,一个是发心跳包的间隔时间,另一个就是等待对方心跳包的最长等待时间。一般等待的时间设置成发心跳包的间隔时间的两倍即可,默认KeepAliveInterval是15秒,ClientTimeoutInterval是30秒,我觉得不需要这么频繁的确认对方“死掉”了没,所以我改成2分钟发一次心跳包,最长等待对方的心跳包时间是4分钟,对应的客户端就得设置

connection.keepAliveIntervalInMilliseconds = 12e4;

connection.serverTimeoutInMilliseconds = 24e4;<br>  注入了SignalR之后,接下来需要使用WebSocket和SignalR,对应代码如下:
//添加WebSocket支持,SignalR优先使用WebSocket传输
            app.UseWebSockets();
            //app.UseWebSockets(new WebSocketOptions
            //{
            //    //发送保持连接请求的时间间隔,默认2分钟
            //    KeepAliveInterval = TimeSpan.FromMinutes(2)
            //});
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapHub<MessageHub>("/msg");
            });

 

 

 

 

 

 

 

获取到js的客户端文件

cdn 

 <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.7/signalr.min.js"></script>

 

 

 

 

 客户端输入以下js

"use strict";

var connection = new signalR.HubConnectionBuilder().withUrl("/signalRHub").build();

//Disable send button until connection is established
document.getElementById("sendButton").disabled = true;

connection.on("ReceiveMessage", function (user, message) {
    console.log(user)
    var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
    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("SendMessageToUser", user, message).catch(function (err) {
        return console.error(err.toString());
    });
    event.preventDefault();
});

效果图

 

posted @ 2021-05-12 15:43  顾小凡  阅读(397)  评论(0)    收藏  举报