Asp.net MVC中实现即时通讯聊天的功能。前几天刚写了一片基础入门的教程,今天就来实现一下使用signaIr实现一对一的聊天的功能,对于这种场景也是即时通讯最基本功能。好吧废话不多说。先来看一下最终实现的效果图:
首先我们先搭建好环境,如果不熟悉,看下前面写的一片文章 MVC中使用signalR入门教程
接着:我们就开始写UserHub.cs 集线器类
主要的步骤就是要:
1. 重写OnConnected连接方法和OnDisconnected断开方法
2.服务器端方法 SendMessage 发送消息 ,GetName获取用户名
3.客户端响应的提示返回信息方法,比如Clients.Client(Context.ConnectionId).addMessage(message) .等等
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Microsoft.AspNet.SignalR; using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Newtonsoft.Json; using Microsoft.AspNet.SignalR.Hubs; namespace SignaIrOneOnOneDemo { [HubName("UserHub")] public class UserHub : Hub { public static List<User> users = new List<User>(); //发送消息 public void SendMessage(string connectionId ,string message) { Clients.All.hello(); var user = users.Where(s => s.ConnectionID == connectionId).FirstOrDefault(); if (user != null) { Clients.Client(connectionId).addMessage(message + "" + DateTime.Now, Context.ConnectionId); //给自己发送,把用户的ID传给自己 Clients.Client(Context.ConnectionId).addMessage(message + "" + DateTime.Now, connectionId); } else { Clients.Client(Context.ConnectionId).showMessage("该用户已离线"); } } [HubMethodName("exitChat")] public void GetName(string name) { //查询用户 var user = users.SingleOrDefault(u => u.ConnectionID == Context.ConnectionId); if (user != null) { user.Name = name; Clients.Client(Context.ConnectionId).showId(Context.ConnectionId); } GetUsers(); } /// <summary> /// 重写连接事件 /// </summary> /// <returns></returns> public override Task OnConnected() { //查询用户 var user = users.Where(w => w.ConnectionID == Context.ConnectionId).SingleOrDefault(); //判断用户是否存在,否则添加集合 if (user == null) { user = new User("", Context.ConnectionId); users.Add(user); } return base.OnConnected(); } public override Task OnDisconnected(bool stopCalled) { var user = users.Where(p => p.ConnectionID == Context.ConnectionId).FirstOrDefault(); //判断用户是否存在,存在则删除 if (user != null) { //删除用户 users.Remove(user); } GetUsers();//获取所有用户的列表 return base.OnDisconnected(stopCalled); } //获取所有用户在线列表 private void GetUsers() { var list = users.Select(s => new { s.Name, s.ConnectionID }).ToList(); string jsonList = JsonConvert.SerializeObject(list); Clients.All.getUsers(jsonList); } } public class User { [Key] public string ConnectionID { get; set; } public string Name { get; set; } public User(string name, string connectionId) { this.Name = name; this.ConnectionID = connectionId; } } }
然后我们来看一下前端页面是怎么写的
@{ ViewBag.Title = "UserChat"; Layout = null; } <h2>UserChat</h2> <script src="~/Scripts/jquery-1.10.2.js"></script> <script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script> <script src="~/signalr/hubs"></script> <script type="text/javascript"> var clients = []; var chat; $(function () { chat = $.connection.UserHub; console.info(chat); //显示提示方法 chat.client.showMessage = function (message) { alert(message); } //注册显示信息的方法 chat.client.addMessage = function (message, connectionId) { debugger if ($.inArray(connectionId, clients)==-1) { showWin(connectionId); } $("#" + connectionId).find("ul").each(function () { $(this).append('<li>'+message+'</li>'); }) } //注册显示所有用户的方法 chat.client.getUsers = function (data) { if (data) { var json = $.parseJSON(data); console.info(json); $("#users").html(" "); for (var i = 0; i < json.length; i++) { var html = '<li>用户名:' + json[i].Name + '<button connectionId="' + json[i].ConnectionID + '" onclick="userChat(this)">聊天</button>'; $("#users").append(html); } } } //注册显示推出聊天提示的方法 chat.client.exitUser = function (data) { alert(data); } //注册显示个人信息的方法 chat.client.showId = function (data) { $("#conId").html(data); clients.push(data); } //获取用户名称 $('#userName').html(prompt('请输入您的名称', '')); //连接成功后获取自己的信息 $.connection.hub.start().done(function () { chat.server.getName($('#userName').html()); }); }); //开始聊天 function userChat(obj) { var connectionId = $(obj).attr('connectionId'); showWin(connectionId); } function showWin(connectionId) { //var connectionId = $(obj).attr('connectionId'); clients.push(connectionId); var html = '<div style="float:left;margin-left:30px;border:double" id="' + connectionId + '" connectionId="' + connectionId + '">' + connectionId + '"的房间聊天记录如下:<button onclick="exitChat(this)">退出</button><ul></ul><input type="text" /> <button onclick="sendMessage(this)">发送</button></div>'; $("#userBox").append(html); } function exitChat(btnObj) { debugger // var connectionId = $(btnObj).parent().attr("connectionId"); $(btnObj).parent().remove(); //chat.server.exitChat(connectionId); } //发送消息 function sendMessage(data) { var message = $(data).prev().val(); var userObj = $(data).parent(); var username = $("#userName").html(); message = username + ":" + message; console.info($(userObj).attr("connectionId")); var targetConnectionId = $(userObj).attr("connectionId"); chat.server.sendMessage(targetConnectionId, message); $(data).prev().val(""); } </script> <div> <div>名称:<p id="userName"></p></div> <div>ConnectionID:<p id="conId"></p></div> <div style="25%;border:1px solid #ff0000"> <div>在线用户列表</div> <ul id="users"></ul> </div> <div id="userBox"> </div> </div>
一个signalr一对一聊天例子就完成了,我们来简单的分析一下吧:
Clients.Client(connectionId).addMessage() 此方法的作用就是客户端注册addMessage方法,向指定连接Id的客户端发送消息。一对一的聊天发送的消息也必须回发给自己,所以连接的Id可以通过Context.ConnectionId来获取。当然不用Client.Client(Context.ConnectionId) ,也可以使用Client.Caller()方法直接发送
Client.Clients(IList<string> connectionIds) 这个方法的意思就是想一组string 的几个ConnectionId发送消息。类似于QQ上@好友的那种功能。
在谷歌浏览器中我们可以看到这些方法
可以很清楚的看到这个三个服务器端的方法,服务器端的方法名在客户端调用的时候都约定成了第一个字母小写了,但是可以通过方法上的特性HubMethodName进行标识。
这个集线器的UserHub也默认是第一个字母小写的,所以在前端写的时候要注意。源码下载地址: