4

我目前将我的用户保存在一个名为 OnlineUsers 的表中。当一个人连接或断开连接时,它会将用户 ID 和他的连接 ID 添加到表中,但由于某种原因(我相信当多个浏览器窗口打开时)断开功能有时不会触发,将用户留在表中并使其显示为“在线” “当他们真的不是的时候。以前有没有人遇到过这个问题,解决这个问题的好方法是什么?

更新**(抱歉没有放代码,我应该首先完成)

这是我要从表中添加和删除的数据库函数:

    public bool ConnectUser(Guid UserId, String ConnectionId)
            {
                if (!Ent.OnlineUsers.Any(x => x.UserId == UserId && x.ConnectionId == ConnectionId))
                {
                    Ent.OnlineUsers.AddObject(new OnlineUser { UserId = UserId, ConnectionId = ConnectionId });
                    Ent.SaveChanges();
                    return true;
                }
                else
                    return false;
            }
            public void DisconnectUser(Guid UserId, String ConnectionId)
            {
                if (Ent.OnlineUsers.Any(x => x.UserId == UserId && x.ConnectionId == ConnectionId))
                {
                    Ent.OnlineUsers.DeleteObject(Ent.OnlineUsers.First(x => x.UserId == UserId && x.ConnectionId == ConnectionId));
                    Ent.SaveChanges();
                }
            }

这是我的集线器类连接和断开任务:

 public Task Disconnect()
        {

            disconnectUser();                
            return null;
        }
        public Task Reconnect(IEnumerable<string> connections)
        {
            connectUser();                
            return null;
        }
        public Task Connect()
        {
            connectUser();               
            return null;
        }
private void connectUser()
        {
            if (onlineUserRepository.ConnectUser(MainProfile.UserId, Context.ConnectionId))
            {
                Groups.Add(Context.ConnectionId, Convert.ToString(MainProfile.ChatId));
            }
        }
        private void disconnectUser()
        {
            onlineUserRepository.DisconnectUser(MainProfile.UserId, Context.ConnectionId);
            Groups.Remove(Context.ConnectionId, Convert.ToString(MainProfile.ChatId));
        }

我已经检查过我使用的是最新版本的 signalR (0.5.3),这似乎发生在我打开多个浏览器窗口并同时关闭它们时,用户将卡在数据库中。

如果需要,这是我的连接 ID 生成器类:

public class MyConnectionFactory : IConnectionIdGenerator
    {
        public string GenerateConnectionId(IRequest request)
        {            
            if (request.Cookies["srconnectionid"] != null)
            {
                return request.Cookies["srconnectionid"].ToString();
            }

            return Guid.NewGuid().ToString();
        }
    }
4

1 回答 1

7

我认为您的连接工厂确实是问题所在。如果您没有找到 cookie,则继续生成新的 guid,但到那时已经太晚了。

我的理解是连接id是由客户端(客户端集线器)在初始化时建立的,不能在服务器端更改;它只能读取。实际上,当您在找不到 cookie 时返回新的 Guid 时,您正在更改客户端 ID。

在我的连接工厂中,如果找不到 cookie,我会抛出。在打开使用信号器的页面的控制器操作中,我确保已植入 cookie。

这是我的连接工厂:

public class ConnectionFactory : IConnectionIdGenerator
{
    public string GenerateConnectionId(IRequest request)
    {
        if (request.Cookies["UserGuid"] != null)
            return request.Cookies["UserGuid"].Value;

        throw new ApplicationException("No User Id cookie was found on this browser; you must have cookies enabled to enter.");
    }
}
于 2012-11-09T02:14:35.630 回答