与 SignalR 进行私人聊天 - 与陌生人交谈
本文关键字:陌生人 交谈 聊天 SignalR | 更新日期: 2023-09-27 18:35:15
我想写一个简单的聊天,原理是 omegle.com。我写道,如果用户进入服务器并且队列为空,则会创建一个新组并落入队列。当另一个人进入时,它会在队列中与此连接。这是我的代码:
public class UserGroup
{
public string GroupName { get; set; }
}
public class ChatHub : Hub
{
public static Queue<UserGroup> Users = new Queue<UserGroup>();
public static string Group { get; set; }
public Task JoinGroup(string groupName)
{
return Groups.Add(Context.ConnectionId, groupName);
}
public override System.Threading.Tasks.Task OnConnected()
{
if(Users.Count == 0)
{
var user = new UserGroup { GroupName = Context.ConnectionId };
Users.Enqueue(user);
Group = user.GroupName;
JoinGroup(user.GroupName);
}
else
{
JoinGroup(Users.Peek().GroupName);
Group = Users.Peek().GroupName;
Users.Dequeue();
}
return base.OnConnected();
}
public void SayHello(string name, string helloMsg)
{
Clients.Caller.Hello(name, helloMsg);
}
public void Send(string msg)
{
Clients.Group(Group).SendMessage(msg);
}
}
不幸的是,当我与其他人联系时,一切都崩溃了,并且不会为新人创建一个新组。所有静态数据,但不幸的是,SignalR 不允许其他数据。您知道如何解决此问题吗?
我认为在这种情况下您不需要队列或使用组。最简单的解决方案是将陌生人的客户端 ID 发送给另一个客户端。应合并锁定,因为您可以从不同的中心实例访问共享状态:
-
创建新的 ASP.NET Web 应用程序项目并选择 MVC 作为框架。
-
添加
Microsoft.AspNet.SignalR
并knockoutjs
nuget 包并更新所有包。 -
当前 SignalR 版本要求添加
Startup
类:public class Startup { public void Configuration(IAppBuilder app) { app.MapSignalR(); } }
-
添加中心类:
public class ChatHub : Hub { private static string waitingUser; private static readonly object SyncLock = new object(); public void SendMessage(string text, string clientId) { this.Clients.Client(clientId).addMessage(text); } public override Task OnConnected() { var newUser = this.Context.ConnectionId; string otherUser; lock (SyncLock) { if (waitingUser == null) { waitingUser = newUser; return base.OnConnected(); } otherUser = waitingUser; waitingUser = null; } this.Clients.Caller.startChat(otherUser); this.Clients.Client(otherUser).startChat(newUser); return base.OnConnected(); } }
-
最后,将以下代码添加到视图中:
@{ ViewBag.Title = "Chat wit a Stranger"; } <h1>Chat with a Stranger</h1> <div data-bind="foreach: messages"> <div data-bind="text: $data"></div> </div> <hr/> <form data-bind="submit: send, visible: connected"> <input type="text" data-bind="value: text" /> <button type="submit">Send</button> </form> <script src="~/Scripts/knockout-3.2.0.debug.js"></script> <script src="~/Scripts/jquery-2.1.1.js"></script> <script src="~/Scripts/jquery.signalR-2.1.2.js"></script> <script src="~/signalr/hubs"></script> <script> var hub = $.connection.chatHub; var vm = { otherUser: "", messages: ko.observableArray(["Waiting for a stranger..."]), connected: ko.observable(false), text: ko.observable(""), send: function () { var text = vm.text(); if (text.length == 0) return; hub.server.sendMessage(text, vm.otherUser); vm.messages.push("You: " + text); vm.text(""); }, addMessage: function(text) { vm.messages.push("Stranger: " + text); }, startChat: function (otherUser) { vm.otherUser = otherUser; vm.messages(["A stranger has connected. Say hello!"]); vm.connected(true); } } ko.applyBindings(vm); hub.client.startChat = vm.startChat; hub.client.addMessage = vm.addMessage; $.connection.hub.start(); </script>