与SignalR私聊 - 与陌生人交谈

时间:2014-12-25 23:44:20

标签: c# .net signalr

我想写一个简单的聊天原则为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不允许这样做。你知道怎么解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

在这种情况下,我认为您不需要队列或使用组。最简单的解决方案是将陌生人的客户端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>