Signalr 信号器-聊天的正确实现

Signalr 信号器-聊天的正确实现,signalr,signalr-hub,signalr.client,signalr-2,Signalr,Signalr Hub,Signalr.client,Signalr 2,我需要在我的web项目上实现聊天。如何在一页上实现它-有很多关于它的文章。但我需要有能力: 1.通知其他用户,有人登录到网站的任何页面,而不仅仅是聊天页面 2.通知其他用户有人注销 因此,我有以下hub代码: public void Connect() { try { var id = Context.ConnectionId; string username = Context.User.Ident

我需要在我的web项目上实现聊天。如何在一页上实现它-有很多关于它的文章。但我需要有能力: 1.通知其他用户,有人登录到网站的任何页面,而不仅仅是聊天页面 2.通知其他用户有人注销

因此,我有以下hub代码:

    public void Connect()
    {
        try
        {
            var id = Context.ConnectionId;
            string username = Context.User.Identity.Name;

            var currentUser = connectedUsers.Where(p => p.Username == username).FirstOrDefault();
            if (currentUser == null)
            {
                AddNewUserToCollection();
            }
            else
            {
                // update ConnectionId for sure (connection id is changed sometimes (probably if user is logged out and login again))
                if (currentUser.ConnectionId != id)
                {
                    var companyId = _chatRepository.GetCompanyIdOfUser(username); // throws exception if companyId is null
                    Groups.Remove(currentUser.ConnectionId, companyId.ToString());
                    Groups.Add(id, companyId.ToString());
                    currentUser.ConnectionId = id;
                    //Clients.Group(companyId.ToString()).onNewUserConnected(username);
                }
            }
        }
        catch(InvalidCompanyException c_ex)
        {
            Clients.Client(Context.ConnectionId).onErrorMessage($"User '{c_ex.Username}' does not exist");
        }
    }


    public void Disconnect()
    {
        string username = Context.User.Identity.Name;
        var item = connectedUsers.Where(p => p.Username == username).FirstOrDefault();
        if (item != null)
        {
            connectedUsers.Remove(item);
            Groups.Remove(item.ConnectionId, item.CompanyID.ToString());
            Clients.Group(item.CompanyID.ToString()).onUserDisconnected(item.Username);
        }
    }

    public override Task OnDisconnected(bool stopCalled)
    {
        var item = connectedUsers.Where(p => p.ConnectionId == Context.ConnectionId).FirstOrDefault();
        if (item != null)
        {
            connectedUsers.Remove(item);
            Groups.Remove(item.ConnectionId, item.CompanyID.ToString());
            Clients.Group(item.CompanyID.ToString()).onUserDisconnected(item.Username);
        }
        return base.OnDisconnected(stopCalled);
    }
我在_layout.cshtml中添加了以下代码:

    <script>
        $(document).ready(function () {
            var chat = $.connection.chatHub;

            $.connection.hub.start().done(function () {
                chat.server.connect();
            });
        });
    </script>

要通知其他用户,当前用户已登录。但调试器说,当用户重新加载页面并通过具有不同connectionId的页面时,每次都会调用disconnected/Connect对。当我删除此客户机代码时,不会调用该对。如何正确地实现它,通知其他用户有人在线,但每次都没有重新连接?

由于您在razor\u layout.cshtml页面中有连接调用,因此在每次回发页面加载时,您将有效地断开/连接

您尝试使用的场景最好是SPA或AJAX场景,其中导航由客户端JavaScript异步处理。您当前的设置是刷新屏幕、重新加载JavaScript、使用每个服务器呈现的导航重新运行document ready函数


另一种方法是使用客户端的实际用户Id,并将其传递给server.connectid方法。然后使用此用户Id来跟踪用户活动,而不是hub ConnectionId。

最基本的版本即将面世。我的建议是,在某人断开连接后等待几秒钟,然后再告诉其他人他们已断开连接,并且只有在用户没有出现新的连接id的情况下。下一个问题是处理打开多个选项卡的用户,您需要跟踪每个用户的连接数。仅供参考,这最好是在一个中心管道,但你应该首先在这里工作。