1. はじめに
前回の記事では、SignalR について詳しく紹介し、Asp.net MVC と WPF での応用について簡単に紹介しました。前回のブログ投稿ではグループ メッセージングの実装を紹介しましたが、SignalR はリアルタイム チャットのために生まれたため、当然ながら QQ とは異なり、エンドツーエンドのチャットがありません。このブログ投稿では、SignalR を使用して QQ チャットと同様の機能を実装する方法を紹介します。
2. SignalR を使用してエンドツーエンド チャットを実装するというアイデア
具体的な実装を紹介する前に、まず SignalR を使用してエンドツーエンド チャットを実装するというアイデアを紹介しました。前の記事で Clients.All.sendMessage(name, message); のようなコードを見たかと思いますが、これはすべてのクライアントの SendMessage を呼び出すことを意味します。 SignalR のハブにより、クライアントとサーバー間のリアルタイム通信が可能になります。エンドツーエンドのチャットを実現するには、当然のことながら、すべてのクライアントにメッセージを送信することはできず、特定のクライアントにのみメッセージを送信することができます。そうしないと、混乱が生じ、プライバシーが失われます。では、特定のクライアントにメッセージを送信するにはどうすればよいでしょうか?この問題は、エンドツーエンドのチャット機能の実装の鍵となります。
All 属性に加えて、送信する Clients オブジェクトには他の属性もあります。VS で F12 を押すと、Clients オブジェクトのすべての属性またはメソッドが表示されます。
public interface IHubConnectionContext<T> { T All { get; } // 代表所有客户端 T AllExcept(params string[] excludeConnectionIds); // 除了参数中的所有客户端 T Client(string connectionId); // 特定的客户端,这个方法也就是我们实现端对端聊天的关键 T Clients(IList<string> connectionIds); // 参数中的客户端端 T Group(string groupName, params string[] excludeConnectionIds); // 指定客户端组,这个也是实现群聊的关键所在 T Groups(IList<string> groupNames, params string[] excludeConnectionIds); T User(string userId); // 特定的用户 T Users(IList<string> userIds); // 参数中的用户 }
。 SignalR では、クライアントの一意性をマークするために、SignalR はそれに ConnectionId を割り当てます。これにより、ConnectionId を通じて特定のクライアントを見つけることができます。このようにして、クライアントにメッセージを送信するときは、メッセージを渡すだけでなく、相手に送信される ConnectionId も入力する必要があります。これにより、サーバーは、メッセージに基づいて対応するクライアントに対応するメッセージを転送できます。受信接続 ID が提供されます。これでエンドツーエンドのチャット機能が完成します。さらに、ユーザーがオンラインでない場合、サーバーは、対応するクライアントがオンラインになると、データベースから、クライアントにプッシュする必要のあるメッセージがあるかどうかを確認し、メッセージを取得できます。データベースからデータを取得し、データをクライアントにプッシュします。 (ただし、サーバー側でデータをキャッシュする機能はこのブログ記事では実装されていません。ここでの紹介は、QQ の実装原則の 1 つを誰もが理解できるようにするためです)。
エンドツーエンドのチャット機能の実装アイデアを整理してみましょう:
クライアントがログインすると、クライアントの ConnectionId が記録され、このデータはすべてのオンライン ユーザーを記録するために使用されます。
ユーザーはオンライン ユーザー間のユーザー チャットをクリックしてメッセージを送信できます。ConnectionId をサーバーに渡す必要があります。
サーバーは、受信メッセージの内容と ConnectionId に基づいて Clients.Client(connection).sendMessage メソッドを呼び出し、対応するクライアントに転送します。
3. クールなチャット機能のコアコードを実装します
実装アイデアを使用すると、機能を簡単に実装できます。 次に、最初にハブ ChatHub のコードを見てみましょう。
上記はサーバーの主要な実装です。クライアントの実装コードを見てみましょう:
public class ChatHub : Hub { // 静态属性 public static List<UserInfo> OnlineUsers = new List<UserInfo>(); // 在线用户列表 /// <summary> /// 登录连线 /// </summary> /// <param name="userId">用户Id</param> /// <param name="userName">用户名</param> public void Connect(string userId, string userName) { var connnectId = Context.ConnectionId; if (OnlineUsers.Count(x => x.ConnectionId == connnectId) == 0) { if (OnlineUsers.Any(x => x.UserId == userId)) { var items = OnlineUsers.Where(x => x.UserId == userId).ToList(); foreach (var item in items) { Clients.AllExcept(connnectId).onUserDisconnected(item.ConnectionId, item.UserName); } OnlineUsers.RemoveAll(x => x.UserId == userId); } //添加在线人员 OnlineUsers.Add(new UserInfo { ConnectionId = connnectId, UserId = userId, UserName = userName, LastLoginTime = DateTime.Now }); } // 所有客户端同步在线用户 Clients.All.onConnected(connnectId, userName, OnlineUsers); } /// <summary> /// 发送私聊 /// </summary> /// <param name="toUserId">接收方用户连接ID</param> /// <param name="message">内容</param> public void SendPrivateMessage(string toUserId, string message) { var fromUserId = Context.ConnectionId; var toUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == toUserId); var fromUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == fromUserId); if (toUser != null && fromUser != null) { // send to Clients.Client(toUserId).receivePrivateMessage(fromUserId, fromUser.UserName, message); // send to caller user // Clients.Caller.sendPrivateMessage(toUserId, fromUser.UserName, message); } else { //表示对方不在线 Clients.Caller.absentSubscriber(); } } /// <summary> /// 断线时调用 /// </summary> /// <param name="stopCalled"></param> /// <returns></returns> public override Task OnDisconnected(bool stopCalled) { var user = OnlineUsers.FirstOrDefault(u => u.ConnectionId == Context.ConnectionId); // 判断用户是否存在,存在则删除 if (user == null) return base.OnDisconnected(stopCalled); Clients.All.onUserDisconnected(user.ConnectionId, user.UserName); //调用客户端用户离线通知 // 删除用户 OnlineUsers.Remove(user); return base.OnDisconnected(stopCalled); } }
上記は、いくつかのコア コード実装のみをリストしています。さらに、クールな効果を実現するために、ここでは Jquery プラグインが使用されています。layer 公式 Web サイトは、http://layer.layui.com/ です。このプラグインは主にポップアップ ボックスとポップアップ レイヤーの効果を実現するために使用されます。フロントエンドにあまり詳しくないため、この JS コードを自分で記述する必要があります。特殊効果コードもインターネット上の実装に基づいています。実行して効果を確認したい場合は、記事の最後にあるソースコードをダウンロードして実行することをお勧めします。
4. 最終的な効果
実装アイデアと実装コードを紹介した後、実装された機能が基本的なチャットを満たすことができるかどうかを確認するというエキサイティングな瞬間が来ました。機能、インターフェイスが十分に優れているかどうかも確認する必要があります。