2014-02-27 48 views
2

我的连接无法启动。 此代码在1.x中工作,但在版本2中不起作用。SignalR Javascript客户端:无法启动连接

SignalR似乎试图连接,但没有成功。 集线器方法永远不会被调用。

附加发送图像与SignalR调试。

的Javascript:

<script type="text/javascript"> 

    $.connection.hub.logging = true; 
    var options = { transport: ['webSockets', 'longPolling'] }; 

    $(function() { 
     var userHub = $.connection.userHub; 

     //Iniciar connecção 
     window.hubReady = $.connection.hub.start(options); 

     window.hubReady.done(function() { 
      userHub.server.ini(); 
     }); 

     userHub.client.iniDone = function (connectionId) { 
      console.log(connectionId); 
     }; 

     $.connection.hub.connectionSlow(function() { 
      console.log('slow connection...'); 
     }); 

     window.hubReady.fail(function(error) { 
      console.log(error); 
     }); 

     $.connection.hub.disconnected(function() { 
      setTimeout(function() { 
       $.connection.hub.start(); 
      }, 2000); 
     }); 

    }); 

</script> 

枢纽:

[HubName("userHub")] 
public class UserHub : Hub 
{ 
    public void Ini() 
    { 
     Clients.Client(Context.ConnectionId).iniDone(string.Format("Conectado com o id: {0}", Context.ConnectionId)); 
    } 

    public override Task OnConnected() 
    { 

     var connectionId = Context.ConnectionId; 
     var email = string.IsNullOrWhiteSpace(Context.User.Identity.Name) ? Context.Headers["email"] : Context.User.Identity.Name; 


     if (email != null && connectionId != null) 
      UserData.GetInstance(email).ConnectionsIds.Add(connectionId); 

     return base.OnConnected(); 
    } 

    public override Task OnDisconnected() 
    { 

     var connectionId = Context.ConnectionId; 
     var email = string.IsNullOrWhiteSpace(Context.User.Identity.Name) ? Context.Headers["email"] : Context.User.Identity.Name; 


     if (email != null && connectionId != null) 
      UserData.GetInstance(email).ConnectionsIds.Remove(connectionId); 

     return base.OnDisconnected(); 
    } 
} 

调试:

SignalR Debug Image

编辑:

我发现了这个问题!我的Singleton的GetInstance方法有问题。

public static UserData GetInstance(string username) 
{ 
    if (_sharedUsers == null) 
     lock (_lockCreate) 
       _sharedUsers = new Dictionary<string, UserData>(); 

    if (!_sharedUsers.ContainsKey(username)) 
     lock (_lockAdd) 
      _sharedUsers.Add(username, new UserData(username)); 

    return _sharedUsers[username]; 
} 

的方法停止总是在这里:锁(_lockAdd)

我要保存所有的用户connectionsIds任何想法?

谢谢

+0

所以在中心服务器上,你看不到“OnConnected”被调用?还是仅仅是“Ini”没有被召唤? –

+0

您列出的调试图像还显示所有连接到服务器的尝试超时。你可以在'http:// localhost:38219'上确认服务器正在运行吗? –

+0

调用了OnConnected和OnDisconnected。 Ini()不叫 – rmlm

回答

1

尝试将客户端方法订阅移动到连接之前。如果连接开始时未注册,则不能从服务器调用。

所以它更改为以下:

$(function() { 
    var userHub = $.connection.userHub; 

    //Register Client handlers first 
    userHub.client.iniDone = function (connectionId) { 
     console.log(connectionId); 
    }; 

    //Now you can connect. 
    window.hubReady = $.connection.hub.start(options); 

    window.hubReady.done(function() { 
     userHub.server.ini(); 
    }); 

    $.connection.hub.connectionSlow(function() { 
     console.log('slow connection...'); 
    }); 

    window.hubReady.fail(function(error) { 
     console.log(error); 
    }); 

    $.connection.hub.disconnected(function() { 
     setTimeout(function() { 
      $.connection.hub.start(); 
     }, 2000); 
    }); 

}); 

编辑

基于围绕该OnConnected方法中的服务器错误您的评论,好像你可能有两个问题即可。将连接跟踪部分隔离出来(只是注释掉)以获得客户端和服务器之间的完整往返行程。然后添加可能是数据库连接错误的连接跟踪 - 检查服务器日志。

编辑

在存储用户连接方面,你几个选项。

使用ConcurrentDictionary

最简单的一种是存储在一个静态ConcurrentDictionary,类似于你有什么。尽量避免使用这么多的锁 - 使用ConcurrentDictionary意味着你实际上最终没有。

例如

public class UserData 
    { 
     public UserData(string username) 
     { 
      UserName = username; 
      ConnectionIds = new HashSet<string>(); 
     } 

     public string UserName { get; private set; } 
     public HashSet<string> ConnectionIds { get; private set; } 
    } 

    public static class ConnectionStore 
    { 
     private static readonly ConcurrentDictionary<string, UserData> _userData = new ConcurrentDictionary<string, UserData>(); 

     public static void Join(string username, string connectionId) 
     { 
      _userData.AddOrUpdate(username, 
       u => new UserData(u),     /* Lambda to call when it's an Add */ 
       (u, ud) => {       /* Lambda to call when it's an Update */ 
        ud.ConnectionIds.Add(connectionId); 
        return ud; 
      }); 
     } 
    } 

查看MSDN了解更多信息:http://msdn.microsoft.com/en-us/library/ee378675(v=vs.110).aspx

使用数据库:

另一种选择是使用数据库来存储(使用实体框架),其中有跟踪用户的好处数据跨服务器回收。

看看http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections,它显示了其他几个选项。

+0

马特我发现了问题!我的Singleton的GetInstance方法有问题。 – rmlm

+0

除非您按上述顺序重新排序,否则在从服务器调用客户端时仍然存在问题。 –

0

有同样的问题了这么久,所以在某些时候放弃了整个signalR,但不得不再次把它捡起来为我们的项目:

我写的答案,可能会导致您和他人的正确的轨道(一步一步)...在回答我使用PersistentConnection而不是集线器,但原则应该是相同的:

https://stackoverflow.com/a/25304790/3940626