2012-11-06 20 views
4

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

更新**(约不把代码对不起,我应该在第一时间完成它)

这里是我的数据库功能,添加和删除表:

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(); 
     } 
    } 
+2

哪个SignalR的版本您使用的?我曾经在0.5.3之前的版本中遇到间歇性问题;从那时起,我的连接/断开已经稳定。此外,张贴源代码是要求能够诊断SignalR问题(或者真的,你在SO上发布的任何问题)。最后,你是否能够在不同的浏览器上测试它们的行为是否有所不同? – Heather

+0

我查了一下,现在我在signalR 0.5.3版上,由于某种原因,它仍然在发生,我可以缩小到多个浏览器窗口打开并且我一次关闭所有这些问题。 – anthonypliu

+0

@ Heather我还添加了我的连接ID创建者,也许这可能是问题的原因 – anthonypliu

回答

7

我觉得你的连接工厂确实是问题。如果你没有找到一个cookie的情况下,你继续前进,并产生一个新的指导,但到那时已经太晚了。

我的理解是,连接ID由客户端(客户端集线器)在初始化过程中建立,并且不能在服务器上更改;它只能被读取。实际上,如果您在未找到Cookie的情况下返回新的Guid,则您正在更改客户端ID。

在我的连接工厂,如果没有找到cookie我扔。在打开正在使用signalr的页面的控制器操作中,我确保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."); 
    } 
} 
+0

如果在创建连接ID的页面上打开了多个浏览器窗口,你会怎么做?在我的情况下,你如何处理多个浏览器窗口。再次感谢您的帮助! – anthonypliu

+0

多个浏览器实例都可以访问同一个cookie,因此它们都将通过相同的ID进行连接,除非每次发布时都更改cookie的值。无论采用哪种方式,无论有多少个浏览器窗口打开,该cookie的值都是ID最终将会显示的内容,如果某些ID具有相同的ID而其他ID具有不同的ID,则无关紧要。 – Heather