有没有办法检测客户端连接/断开连接?

时间:2021-04-02 05:01:18

标签: asp.net-core

我正在寻找一种 ASP.NET Core 范围内的技术来替代我的 WCF 应用程序,服务器需要知道每个客户端的连接状态(以防客户端 PC 关闭或网络问题)。

据我所知,signalR 在交通层是基于 WebSocket 的,Hubs API 提供 OnConnectedAsync 和 OnDisconnectedAsync 虚拟方法来管理和跟踪连接,而 web api 或 gRPC 基于无状态的 HTTP 协议。

所以我的问题是:ASP.NET Core 中是否有任何方法或技术支持检测客户端连接/断开连接?

非常感谢。

1 个答案:

答案 0 :(得分:0)

据我所知,目前Asp.net core SignalR没有内置方法来检查组是否为空或组中是否存在任何客户端。从 official document 中,我们还可以发现:

连接重新连接时不会保留组成员身份。重新建立连接时,需要重新加入组。无法计算组的成员数量,因为如果应用程序扩展到多台服务器,则此信息不可用。

为了检测客户端连接或断开,作为一种解决方法,在 hub 方法中,您可以定义一个全局变量来存储组名和在线计数,或者您可以存储用户信息(用户名、组名、在线状态等)在数据库中。

在OnConnectedAsync方法中,您可以将用户添加到组并计算在线人数或更改用户的在线状态,在OnDisconnectedAsync方法中,您可以从组中删除用户并更改在线人数。创建一个自定义方法来检查/获取在线用户数。

这样的代码(在此示例代码中,我使用登录用户名创建组,您可以根据您的情况更改它):

[Authorize]
public class ChatHub : Hub
{
    private static Dictionary<string, int> onlineClientCounts = new Dictionary<string, int>();

    public override Task OnConnectedAsync()
    { 
        var IdentityName = Context.User.Identity.Name;
        Groups.AddToGroupAsync(Context.ConnectionId, IdentityName);

        int count = 0;
        if (onlineClientCounts.TryGetValue(IdentityName, out count))
            onlineClientCounts[IdentityName] = count + 1;//increment client number
        else
            onlineClientCounts.Add(IdentityName, 1);// add group and set its client number to 1


        return base.OnConnectedAsync();
    }
    public async Task SendMessage(string user, string message)
    { 
        
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }

    public async Task SendMessageToGroup(string sender, string groupname, string message)
    { 
        //check if group contains clients or not via the global variable or check database.

        await Clients.Group(groupname).SendAsync("ReceiveMessage", sender, message);
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        var IdentityName = Context.User.Identity.Name;
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, IdentityName);

        int count = 0;
        if (onlineClientCounts.TryGetValue(IdentityName, out count))
        {
            if (count == 1)//if group contains only 1client
                onlineClientCounts.Remove(IdentityName);
            else
                onlineClientCounts[IdentityName] = count - 1;
        } 

        await base.OnDisconnectedAsync(exception);
    }
}