繁体   English   中英

SignalR Javascript客户端:无法启动连接

[英]SignalR Javascript Client: Cannot Start Connection

我的连接无法启动。 此代码在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调试映像

编辑:

我发现了问题! 我的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)

我想保存所有用户连接Ids有什么想法吗?

谢谢

尝试在连接之前将客户端方法预订移到。 如果在启动连接时尚未注册,则无法从服务器调用它。

因此,将其更改为以下内容:

$(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/zh-cn/library/ee378675(v=vs.110).aspx

使用数据库:

另一个选择是存储在数据库中(使用Entity Framework),该数据库具有在跨服务器回收跟踪用户数据方面的额外好处。

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

长期存在相同的问题,因此在某个时候放弃了整个signalR,但不得不为我们的项目再次选择它:

我写了一个答案,可能会引导您和其他人走上正确的道路……在答案中,我使用的是PersistentConnection而不是Hub,但原理应相同:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM