我正在使用 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 List<User> Users = new List<User>();
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<string, string, DateTime>("broadcastMessage",
(name, message, date) => Context.Post(
delegate {
Messages.Add(new UserMessage() { Message = message, User = name, Date = date });
}, null
)
);
//Receive all online users
chat.On<string>("connected",
(users) => Context.Post(
delegate
{
List<User> userList = JsonConvert.DeserializeObject<List<User>>(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<string>("userConnected",
(user) => Context.Post(
delegate
{
User newUser = JsonConvert.DeserializeObject<User>(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<string>("userLeft",
(user) => Context.Post(
delegate
{
User newUser = JsonConvert.DeserializeObject<User>(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
互联网浏览器 11
最佳答案
我想您的问题是如何检测特定用户是否离开或关闭了浏览器。当用户进来或离开时,向其他用户发送通知。
我认为问题在于您没有正确处理 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>
}
关于javascript - 何时从浏览器关闭与 SignalR 的连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21031160/