我正在与SignalR 2.0进行一些聊天应用程序(就像每个人一样).
我有一个win8.1应用程序,当应用程序关闭时,集线器接收OnDisconnected事件并从集线器上的列表中删除用户.集线器向每个客户端发送用户已离开聊天的内容,因此我们可以看到用户已离开.
但是当我在网页中使用SignalR和Javascript并且页面关闭时,集线器不会收到选项卡/浏览器关闭的通知...
任何人都知道如何关闭连接?
我编码的内容:
启动中心
[assembly: OwinStartup(typeof(ChatServer.Startup))] namespace ChatServer { public class Startup { public void Configuration(IAppBuilder app) { // Map all hubs to "/signalr" app.MapSignalR(); } } }
毂
[HubName("ChatHub")] public class ChatHub : Hub { private static ListUsers = new List (); public void Send(string name, string message) { // Call the broadcastMessage method to update clients. Clients.All.broadcastMessage(name, message, DateTime.Now); } public void UserConnected(string name) { Clients.Caller.connected(JsonConvert.SerializeObject(Users)); User user = new User() { Name = name, ConnectionID = Context.ConnectionId }; Clients.Others.userConnected(JsonConvert.SerializeObject(user)); Users.Add(user); } public void UserLeft() { if(Users.Any(x=>x.ConnectionID == Context.ConnectionId)) { User user = Users.First(x => x.ConnectionID == Context.ConnectionId); Users.Remove(user); Clients.Others.userLeft(JsonConvert.SerializeObject(user), Context.ConnectionId); } } public override System.Threading.Tasks.Task OnDisconnected() { // Only called when win8.1 app closes // Not called when browsers closes page UserLeft(); return base.OnDisconnected(); } }
HTML - Javascript:
使用Javascript:
chat = new function () { var ChatHub; // Connecting to the hub this.attachEvents = function () { if ($.connection != null) { ChatHub = $.connection.ChatHub; $.connection.hub.start({ transport: 'auto' }, function () { // Register client on hub ChatHub.server.userConnected("web name"); }); } this.send = function (name,message) { if ($.connection != null) { //Send chat message ChatHub.server.send(name, message).fail(function (e) { alert(e); }); } } } }; window.onbeforeunload = function (e) { //This is called when we close the page $.connection.hub.stop(); return "You killed me! :'("; };
Win8.1客户端
internal async void ConnectToHub(string userName) { try { HubConnection hubConnection = new HubConnection(SERVER_PROXY); chat = hubConnection.CreateHubProxy("ChatHub"); Context = SynchronizationContext.Current; MakeHubFunctionsAvailableOnClient(); await hubConnection.Start(); // Register client on hub await chat.Invoke("UserConnected", userName); } catch (Exception) { throw; } } private void MakeHubFunctionsAvailableOnClient() { //Receive chat messages chat.On("broadcastMessage", (name, message, date) => Context.Post( delegate { Messages.Add(new UserMessage() { Message = message, User = name, Date = date }); }, null ) ); //Receive all online users chat.On ("connected", (users) => Context.Post( delegate { List userList = JsonConvert.DeserializeObject >(users); foreach (User user in userList) { Users.Add(user); } Messages.Add(new UserMessage() { Message = "CONNECTED", User = "System", Date = DateTime.Now }); }, null ) ); //New user connected chat.On
("userConnected", (user) => Context.Post( delegate { User newUser = JsonConvert.DeserializeObject (user); Users.Add(newUser); Messages.Add(new UserMessage() { Message = newUser.Name + " CONNECTED", User = "System", Date = DateTime.Now }); }, null ) ); //User left, remove user from list on client chat.On ("userLeft", (user) => Context.Post( delegate { User newUser = JsonConvert.DeserializeObject (user); User y = Users.First(x=>x.ConnectionID == newUser.ConnectionID); bool ux = Users.Remove(y); Messages.Add(new UserMessage() { Message = newUser.Name + " left the conversation", User = "System", Date = DateTime.Now }); }, null ) ); }
当我关闭标签/浏览器/导航到其他网站时,我的集线器不会触发OnDisconnected该网站是一个单页网站(暂时)
我用的是什么浏览器?
Chrome:版本32.0.1700.68 beta-m
Internet Explorer 11
您可能会遇到此处描述的问题:https : //github.com/SignalR/SignalR/issues/2719
tl; dr:Chrome 31中引入了一个错误,该错误已在Chrome Canary中修复,可以防止SignalR立即触发OnDisconnected。
如果是这样,可以使用我在问题中建议的解决方法,即将以下内容添加到您的JS代码中。
window.onbeforeunload = function (e) { $.connection.hub.stop(); };
即使存在此错误且没有解决方法,我也希望SignalR在浏览器退出托管SignalR的页面后约35秒内提高OnDisconnected。
您能否提供有关使用哪种浏览器以及在什么情况下遇到此问题的更多详细信息?(例如,关闭标签页,关闭窗口,刷新,导航到同一站点上的另一页,导航到其他站点等)
我想你的问题是如何检测特定用户是否离开或关闭了浏览器.当用户进入或离开时,向其他用户发送通知.
我认为这个问题是你没有处理好OnConnected
和OnDisconnected
正确.要使其工作,首先您需要知道连接到集线器的每个客户端都传递唯一的连接ID.您可以在集线器上下文的Context.ConnectionId属性中检索此值.当每个客户进来时,他们会经过OnConnected
,当他们离开时,他们会经历OnDisconnected
.以下是一个工作示例:
轮毂类
[HubName("ChatHub")] public class ChatHub : Hub { private static List<User> Users = new List<User>(); public void Send(string message) { var name = Context.User.Identity.Name; Clients.All.broadcastMessage(name, message, DateTime.Now.ToShortDateString()); } public override Task OnConnected() { User user = new User() { Name = Context.User.Identity.Name, ConnectionID = Context.ConnectionId }; Users.Add(user); Clients.Others.userConnected(user.Name); return base.OnConnected(); } public override Task OnDisconnected() { if (Users.Any(x => x.ConnectionID == Context.ConnectionId)) { User user = Users.First(x => x.ConnectionID == Context.ConnectionId); Clients.Others.userLeft(user.Name); Users.Remove(user); } return base.OnDisconnected(); } }
视图
<input type="text" id="message" /> <button class="btn">Send</button> <ul id="contents"></ul> @section scripts { <script src="~/Scripts/jquery-1.10.2.js"></script> <script src="~/Scripts/jquery.signalR-2.0.1.js"></script> <script src="/signalr/hubs"></script> <script> var chatHub = $.connection.ChatHub; chatHub.client.broadcastMessage = function (name, message, time) { var encodedName = $('<div />').text(name).html(); var encodedMsg = $('<div />').text(message).html(); var encodedTime = $('<div />').text(time).html(); $('#contents').append('<li><strong>' + encodedName + '</strong>: ' + encodedMsg + '</strong>: ' + encodedTime + '</li>'); }; chatHub.client.userConnected = function (data) { $('#contents').append('<li>Wellcome<strong>' + '</strong>:' + data + '</li>'); }; chatHub.client.userLeft = function (data) { $('#contents').append('<li>Bye<strong>' + '</strong>:' + data + '</li>'); }; $(".btn").on("click", function() { chatHub.server.send($("#message").val()); }); $.connection.hub.start().done(function() { console.log("connected..."); }); </script> }