Heim  >  Artikel  >  Backend-Entwicklung  >  Asp.net verwendet SignalR, um Chatroom-Funktionen zu implementieren

Asp.net verwendet SignalR, um Chatroom-Funktionen zu implementieren

高洛峰
高洛峰Original
2016-12-24 14:20:381960Durchsuche

1. Einführung
Im vorherigen Artikel „Asp.net verwendet SignalR, um eine coole End-to-End-Chat-Funktion zu implementieren“ habe ich Ihnen vorgestellt, wie Sie die End-to-End-Chat-Funktion implementieren In diesem Artikel erfahren Sie, wie Sie mit SignalR Funktionen wie Gruppenchat implementieren.

2. Implementierungsideen
Um die Gruppenchat-Funktion zu implementieren, müssen wir zunächst einen Raum erstellen, und dann kann jeder Online-Benutzer diesem Raum für den Gruppenchat beitreten. Wir können einen eindeutigen Benutzernamen für den Raum festlegen . Der Name dient als Identifikator. Gibt es eine solche Methode in der SignalR-Klassenbibliothek? Die Antwort ist ja.

// IGroupManager接口提供如下方法
// 作用:将连接ID加入某个组
// Context.ConnectionId 连接ID,每个页面连接集线器即会产生唯一ID
// roomName分组的名称
Groups.Add(Context.ConnectionId, roomName);
 
// 作用:将连接ID从某个分组移除
Groups.Remove(Context.ConnectionId, roomName);
 
// IHubConnectionContext接口提供了如下方法
// 调用客户端方法向房间内所有用户群发消息
// Room:分组名称
// new string[0]:过滤(不发送)的连接ID数组
 Clients.Group(Room, new string[0]).clientMethod


Der obige Code ist die Kernmethode zur Implementierung des Gruppenchats. Um es ganz klar auszudrücken: Das Groups-Objekt ist nur ein Listenobjekt, das von der SignalR-Klassenbibliothek verwaltet wird. Tatsächlich können wir ein Dictionary> selbst verwalten Geben Sie den Namen des Raums ein und geben Sie ihn ein. Die ConnectionId des Clients wird zu diesem Wörterbuch hinzugefügt. Wenn Sie dann auf klicken, um eine Nachricht im Chatroom zu senden, finden wir alle ConnectionIds, die dem Gruppenchat beitreten, basierend auf dem Raumnamen, und rufen dann auf Clients.Clients(IList ConnectionIds)-Methode zum Senden der Nachricht „Broadcast“ an jeden Client. Das Obige ist das Prinzip der Implementierung eines Chatrooms.

3. Verwenden Sie SignalR, um die Chatroom-Funktion zu implementieren.
Nachdem wir die Implementierungsideen geklärt haben, werfen wir einen Blick auf den spezifischen Implementierungscode. Gleichzeitig können Sie auch den Code vergleichen, um ihn mit dem vorherigen zu vergleichen Umsetzungsideen.
Sehen Sie sich zunächst den Implementierungscode der Entitätsklasse an, die an der Chatroom-Funktion beteiligt ist:

/// <summary>
 /// 用户类
 /// </summary>
 public class User
 {
  /// <summary>
  /// 用户Id
  /// </summary>
  public string UserId { get; set; }
 
  /// <summary>
  /// 用户的连接集合
  /// </summary>
  public List<Connection> Connections { get; set; }
 
  /// <summary>
  /// 用户房间集合,一个用户可以加入多个房间
  /// </summary>
  public List<ChatRoom> Rooms { get; set; }
 
  public User()
  {
   Connections = new List<Connection>();
   Rooms = new List<ChatRoom>();
  }
 }
 
 public class Connection
 {
  //连接ID
  public string ConnectionId { get; set; }
 
  //用户代理
  public string UserAgent { get; set; }
  //是否连接
  public bool Connected { get; set; }
 }
 
  /// <summary>
 /// 房间类
 /// </summary>
 public class ChatRoom
 {
  // 房间名称
  public string RoomName { get; set; }
 
  // 用户集合
  public List<User> Users { get; set; }
 
  public ChatRoom()
  {
   Users = new List<User>();
  }
 }
 
 /// <summary>
 /// 上下文类,用来模拟EF中的DbContext
 /// </summary>
 public class ChatContext
 {
  public List<User> Users { get; set; }
 
  public List<Connection> Connections { get; set; }
 
  public List<ChatRoom> Rooms { get; set; }
 
  public ChatContext()
  {
   Users = new List<User>();
   Connections = new List<Connection>();
   Rooms = new List<ChatRoom>();
  }
 }



2. Weiter Sehen wir uns die Implementierung des Hubs an:

[HubName("chatRoomHub")]
 public class GroupsHub : Hub
 {
  public static ChatContext DbContext = new ChatContext();
 
  #region IHub Members
  // 重写Hub连接事件
  public override Task OnConnected()
  {
   // 查询用户
   var user = DbContext.Users.FirstOrDefault(u => u.UserId == Context.ConnectionId);
 
   if (user == null)
   {
    user = new User
    {
     UserId = Context.ConnectionId
    };
 
    DbContext.Users.Add(user);
   }
 
   // 发送房间列表
   var items = DbContext.Rooms.Select(p => new {p.RoomName});
   Clients.Client(this.Context.ConnectionId).getRoomList(JsonHelper.ToJsonString(items.ToList()));
   return base.OnConnected();
  }
 
  // 重写Hub连接断开的事件
  public override Task OnDisconnected(bool stopCalled)
  {
   // 查询用户
   var user = DbContext.Users.FirstOrDefault(u => u.UserId == Context.ConnectionId);
 
   if (user != null)
   {
    // 删除用户
    DbContext.Users.Remove(user);
 
    // 从房间中移除用户
    foreach (var item in user.Rooms)
    {
     RemoveUserFromRoom(item.RoomName);
    }
   }
   return base.OnDisconnected(stopCalled);
  }
 
  #endregion
 
  #region Public Methods
 
  // 为所有用户更新房间列表
  public void UpdateRoomList()
  {
   var itme = DbContext.Rooms.Select(p => new {p.RoomName});
   var jsondata = JsonHelper.ToJsonString(itme.ToList());
   Clients.All.getRoomlist(jsondata);
  }
 
  /// <summary>
  /// 加入聊天室
  /// </summary>
  public void JoinRoom(string roomName)
  {
   // 查询聊天室
   var room = DbContext.Rooms.Find(p => p.RoomName == roomName);
 
   // 存在则加入
   if (room == null) return;
 
   // 查找房间中是否存在此用户
   var isExistUser = room.Users.FirstOrDefault(u => u.UserId == Context.ConnectionId);
 
   // 不存在则加入
   if (isExistUser == null)
   {
    var user = DbContext.Users.Find(u => u.UserId == Context.ConnectionId);
    user.Rooms.Add(room);
    room.Users.Add(user);
     
    // 将客户端的连接ID加入到组里面
    Groups.Add(Context.ConnectionId, roomName);
 
    //调用此连接用户的本地JS(显示房间)
    Clients.Client(Context.ConnectionId).joinRoom(roomName);
   }
   else
   {
    Clients.Client(Context.ConnectionId).showMessage("请勿重复加入房间!");
   }
  }
 
  /// <summary>
  /// 创建聊天室
  /// </summary>
  /// <param name="roomName"></param>
  public void CreateRoom(string roomName)
  {
   var room = DbContext.Rooms.Find(a => a.RoomName == roomName);
   if (room == null)
   {
    var cr = new ChatRoom
    {
     RoomName = roomName
    };
 
    //将房间加入列表
    DbContext.Rooms.Add(cr);
 
    // 本人加入聊天室
    JoinRoom(roomName);
    UpdateRoomList();
   }
   else
   {
    Clients.Client(Context.ConnectionId).showMessage("房间名重复!");
   }
  }
 
  public void RemoveUserFromRoom(string roomName)
  {
   //查找房间是否存在
   var room = DbContext.Rooms.Find(a => a.RoomName == roomName);
 
   //存在则进入删除
   if (room == null)
   {
    Clients.Client(Context.ConnectionId).showMessage("房间名不存在!");
    return;
   }
 
   // 查找要删除的用户
   var user = room.Users.FirstOrDefault(a => a.UserId == Context.ConnectionId);
   // 移除此用户
   room.Users.Remove(user);
   //如果房间人数为0,则删除房间
   if (room.Users.Count <= 0)
   {
    DbContext.Rooms.Remove(room);
   }
 
   Groups.Remove(Context.ConnectionId, roomName);
 
   //提示客户端
   Clients.Client(Context.ConnectionId).removeRoom("退出成功!");
  }
 
  /// <summary>
  /// 给房间内所有的用户发送消息
  /// </summary>
  /// <param name="room">房间名</param>
  /// <param name="message">信息</param>
  public void SendMessage(string room, string message)
  {
   // 调用房间内所有客户端的sendMessage方法
   // 因为在加入房间的时候,已经将客户端的ConnectionId添加到Groups对象中了,所有可以根据房间名找到房间内的所有连接Id
   // 其实我们也可以自己实现Group方法,我们只需要用List记录所有加入房间的ConnectionId
   // 然后调用Clients.Clients(connectionIdList),参数为我们记录的连接Id数组。
   Clients.Group(room, new string[0]).sendMessage(room, message + " " + DateTime.Now);
  }
  #endregion
}



3. Die Code-Implementierung des oben genannten SignalR-Servers ist abgeschlossen , lasst uns fortfahren Werfen wir einen Blick auf die Implementierung der Client-Ansicht:

@{
 Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
 <meta name="viewport" content="width=device-width" />
 <title>Index</title>
 <script src="~/Scripts/jquery-2.2.2.min.js"></script>
 <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
 <script src="~/Scripts/layer/layer.min.js"></script>
 <!--这里要注意,这是虚拟目录,也就是你在OWIN Startup中注册的地址-->
 <script src="/signalr/hubs"></script>
 
 <script type="text/javascript">
  var chat;
  var roomcount = 0;
   
  $(function() {
   chat = $.connection.chatRoomHub;
   chat.client.showMessage = function(message) {
    alert(message);
   };
   chat.client.sendMessage = function(roomname, message) {
    $("#" + roomname).find("ul").each(function() {
     $(this).append(&#39;<li>&#39; + message + &#39;</li>&#39;);
    });
   };
   chat.client.removeRoom = function(data) {
    alert(data);
   };
   chat.client.joinRoom = function (roomname) {
    var html = &#39;<p style="float:left; margin-left:360px; border:double; height:528px;width:493px" id="&#39; + roomname + &#39;" roomname="&#39; + roomname + &#39;"><button onclick="RemoveRoom(this)">退出</button>\
         &#39; + roomname + &#39;房间\
            聊天记录如下:<ul>\
            </ul>\
         <textarea class="ChatCore_write" id="ChatCore_write" style="width:400px"></textarea> <button onclick="SendMessage(this)">发送</button>\
         </p>&#39;;
    $("#RoomList").append(html);
   };
 
   //注册查询房间列表的方法
   chat.client.getRoomlist = function(data) {
    if (data) {
     var jsondata = $.parseJSON(data);
     $("#roomlist").html(" ");
     for (var i = 0; i < jsondata.length; i++) {
      var html = &#39; <li>房间名:&#39; + jsondata[i].RoomName + &#39;<button roomname="&#39; + jsondata[i].RoomName + &#39;" onclick="AddRoom(this)">加入</button></li>&#39;;
      $("#roomlist").append(html);
     }
    }
   };
   // 获取用户名称。
   $(&#39;#username&#39;).html(prompt(&#39;请输入您的名称:&#39;, &#39;&#39;));
 
   $.connection.hub.start().done(function() {
    $(&#39;#CreatRoom&#39;).click(function() {
     chat.server.createRoom($("#Roomname").val());
    });
   });
  });
   
  function SendMessage(btn) {
   var message = $(btn).prev().val();
   var room = $(btn).parent();
   var username = $("#username").html();
   message = username + ":" + message;
   var roomname = $(room).attr("roomname");
   chat.server.sendMessage(roomname, message);
   $(btn).prev().val(&#39;&#39;).focus();
  }
   
  function RemoveRoom(btn) {
   var room = $(btn).parent();
   var roomname = $(room).attr("roomname");
   chat.server.removeUserFromRoom(roomname);
  }
   
  function AddRoom(roomname) {
   var data =$(roomname).attr("roomname");
   chat.server.joinRoom(data);
  }
 
 </script>
</head>
<body>
 <p>
  <p>名称:<p id="username"></p></p>
  输入房间名:
  <input type="text" value="聊天室1" id="Roomname" />
  <button id="CreatRoom">创建聊天室</button>
 </p>
 <p style="float:left;border:double">
  <p>房间列表</p>
  <ul id="roomlist"></ul>
 </p>
 <p id="RoomList">
 </p>
</body>
</html>


4. Nach den oben genannten 3 Schritten der Chatroom Funktion ist abgeschlossen. Bevor wir uns die spezifischen Effekte ansehen, hier ein Hilfscode:

/// <summary>
 /// JSON 帮助类
 /// </summary>
 public class JsonHelper
 {
  /// <summary>
  /// 从一个对象信息生成Json字符串
  /// </summary>
  /// <param name="obj"></param>
  /// <returns></returns>
  public static string ToJsonString(object obj)
  {
   return JsonConvert.SerializeObject(obj);
  }
 
  /// <summary>
  /// 从Json字符串生成对象
  /// </summary>
  /// <typeparam name="T"></typeparam>
  /// <param name="jsonString"></param>
  /// <returns></returns>
  public static T ToObject<T>(string jsonString)
  {
   return JsonConvert.DeserializeObject<T>(jsonString);
  }
 }


4. Laufergebnisse

Als nächstes werfen wir einen detaillierten Blick auf den Betriebseffekt der Chatroom-Funktion. Der spezifische Betriebseffekt ist in der folgenden Abbildung dargestellt:

Asp.net verwendet SignalR, um Chatroom-Funktionen zu implementieren

An diesem Punkt sind alle Der Inhalt dieses Artikels wurde vorgestellt. In einem Artikel wird erläutert, wie mit SignalR die Funktion zum Senden von Bildern realisiert wird.

Weitere Artikel im Zusammenhang mit Asp.net, das SignalR zur Implementierung von Chatroom-Funktionen verwendet, finden Sie auf der chinesischen PHP-Website!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn