.NET Core 基于Websocket的在线聊天室实现

2020-03-05 14:03:29王冬梅

在Hanle方法等待客户端的消息

 private async Task Handle(WebsocketClient webSocket)
 {
  WebsocketClientCollection.Add(webSocket);
  _logger.LogInformation($"Websocket client added.");
  
  WebSocketReceiveResult result = null;
  do
  {
  var buffer = new byte[1024 * 1];
  result = await webSocket.WebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
  if (result.MessageType == WebSocketMessageType.Text && !result.CloseStatus.HasValue)
  {
   var msgString = Encoding.UTF8.GetString(buffer);
   _logger.LogInformation($"Websocket client ReceiveAsync message {msgString}.");
   var message = JsonConvert.DeserializeObject<Message>(msgString);
   message.SendClientId = webSocket.Id;
   MessageRoute(message);
  }
  }
  while (!result.CloseStatus.HasValue);
  WebsocketClientCollection.Remove(webSocket);
  _logger.LogInformation($"Websocket client closed.");
 }

在MessageRoute方法内对客户端的消息进行转发

对客户端的消息定义几个标准的action,对不同的action进行特定的处理,比如加入房间、离开房间、在房间内广播消息等。

private void MessageRoute(Message message)
 {
  var client = WebsocketClientCollection.Get(message.SendClientId);
  switch (message.action)
  {
  case "join":
   client.RoomNo = message.msg;
   client.SendMessageAsync($"{message.nick} join room {client.RoomNo} success .");
   _logger.LogInformation($"Websocket client {message.SendClientId} join room {client.RoomNo}.");
   break;
  case "send_to_room":
   if (string.IsNullOrEmpty(client.RoomNo))
   {
   break;
   }
   var clients = WebsocketClientCollection.GetRoomClients(client.RoomNo);
   clients.ForEach(c =>
   {
   c.SendMessageAsync(message.nick + " : " + message.msg);
   });
   _logger.LogInformation($"Websocket client {message.SendClientId} send message {message.msg} to room {client.RoomNo}");

   break;
  case "leave":
   var roomNo = client.RoomNo;
   client.RoomNo = "";
   client.SendMessageAsync($"{message.nick} leave room {roomNo} success .");
   _logger.LogInformation($"Websocket client {message.SendClientId} leave room {roomNo}");
   break;
  default:
   break;
  }
 }

新建WebsocketClientCollection管理类

这个类是个容器,用来存放所有的websocket链接,便于统一管理。

 public class WebsocketClientCollection
 {
 private static List<WebsocketClient> _clients = new List<WebsocketClient>();

 public static void Add(WebsocketClient client)
 {
  _clients.Add(client);
 }

 public static void Remove(WebsocketClient client)
 {
  _clients.Remove(client);
 }

 public static WebsocketClient Get(string clientId)
 {
  var client = _clients.FirstOrDefault(c=>c.Id == clientId);

  return client;
 }

 public static List<WebsocketClient> GetRoomClients(string roomNo)
 {
  var client = _clients.Where(c => c.RoomNo == roomNo);
  return client.ToList();
 }
 }

在Startup中使用中间件