【问题标题】:SignalR Javascript Client: Cannot Start ConnectionSignalR Javascript 客户端:无法启动连接
【发布时间】:2014-03-31 16:02:21
【问题描述】:

我的连接没有启动。 此代码在 1.x 中有效,但在版本 2 中无效。

SignalR 似乎正在尝试连接但没有成功。 永远不会调用 hub 方法。

附加发送带有 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];
}

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

我想保存所有用户connectionsIds有什么想法吗?

谢谢

【问题讨论】:

  • 所以在服务器上的集线器中,您没有看到OnConnected 被调用?还是只是 Ini 没有被调用?
  • 您列出的调试图像还显示所有连接服务器的尝试都超时。你能确认http://localhost:38219 的服务器正在运行吗?
  • OnConnected 和 OnDisconnected 被调用。 Ini() 没有被调用
  • 是的,它在 IIS Express 上运行
  • 那么在调试服务器的时候,你能看到OnConnected成功完成了吗?只是试图排除任何服务器错误。

标签: c# javascript asp.net-mvc signalr


【解决方案1】:

同样的问题很久了,所以在某个时候放弃了整个 signalR,但不得不为我们的项目再次选择它:

我已经写了一个答案,可能会引导你和其他人走上正确的轨道(一步一步)......在答案中我使用的是 PersistentConnection 而不是 Hub,但原理应该是相同的:

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

【讨论】:

    【解决方案2】:

    尝试将客户端方法订阅移动到连接之前。如果在连接开始时它还没有注册,那么它就不能从服务器调用。

    所以改成下面这样:

    $(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,它显示了所有这些选项以及其他选项。

    【讨论】:

    • 马特我发现了问题!我的 Singleton 的 GetInstance 方法有问题。
    • 你仍然会遇到从服务器调用客户端的问题,除非你按照上面的方法重新排序。
    猜你喜欢
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多