与 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 不允许其他数据。您知道如何解决此问题吗?

与 SignalR 进行私人聊天 - 与陌生人交谈

我认为在这种情况下您不需要队列或使用组。最简单的解决方案是将陌生人的客户端 ID 发送给另一个客户端。应合并锁定,因为您可以从不同的中心实例访问共享状态:

  1. 创建新的 ASP.NET Web 应用程序项目并选择 MVC 作为框架。

  2. 添加Microsoft.AspNet.SignalRknockoutjs nuget 包并更新所有包。

  3. 当前 SignalR 版本要求添加Startup类:

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
    
  4. 添加中心类:

    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();
        }
    }
    
  5. 最后,将以下代码添加到视图中:

    @{
        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>