2014-02-27 115 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