我想写一个简单的聊天原则为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不允许这样做。你知道怎么解决这个问题吗?
答案 0 :(得分:0)
在这种情况下,我认为您不需要队列或使用组。最简单的解决方案是将陌生人的客户端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>