先看下最终实现效果图
预览地址:http://www.mkadmin.cn/
开发步骤:
一:因为整个推送都是使用SignalR来完成,所以先添加引用SignalR
Install-Package Microsoft.AspNet.SignalR
二:编写代码,由于篇幅原因,这里只暂时核心代码
1. SignalR后台推送逻辑
public class HubMain : Hub
{
//保存客户端链接
public static List<UserChatIdentifyMainInfo> userHubMain = new List<UserChatIdentifyMainInfo>();
public static object SetParamLock = new object();
public void InitConnection(UserChatIdentifyMainInfo clientInfo)
{
//防止多个线程同时进入
lock (SetParamLock)
{
if (clientInfo == null)
{
clientInfo = new UserChatIdentifyMainInfo();
}
string connectionId = Context.ConnectionId;
var connList = userHubMain.Where(q => q.ConnectionId == connectionId);
if (!connList.Any())
{
clientInfo.HeadUrl = $"/images/userHead/{(new Random()).Next(1, 100).ToString()}.jpg";
clientInfo.NickName = (new Random()).Next(1000, 9999).ToString();
clientInfo.ConnectionId = connectionId;
//新增
userHubMain.Add(clientInfo);
//通知其他客户端有新用户上线
List<string> connectionIds = userHubMain.Where(q => q.ConnectionId != connectionId).Select(q => q.ConnectionId).ToList();
if (connectionIds != null && connectionIds.Count > 0)
{
Clients.Clients(connectionIds).noticeClientOnLine(clientInfo);
}
//通知自己所有客户端信息
var otherClients = userHubMain.Where(q => q.ConnectionId != connectionId).ToList();
if (otherClients.Any())
{
Clients.Client(connectionId).loadClientAll(otherClients);
}
}
Thread.Sleep(200);
}
}
public override Task OnDisconnected(bool stopCalled)
{
string connectionId = Context.ConnectionId;
//移除客户端链接
userHubMain = userHubMain.Where(q => q.ConnectionId != connectionId).ToList();
//通知客户端
List<string> connectionIds = userHubMain.Select(q => q.ConnectionId).ToList();
if (connectionIds != null && connectionIds.Count > 0)
{
Clients.Clients(connectionIds).noticeClientOnDisconnected(connectionId);
}
return base.OnDisconnected(stopCalled);
}
#region 发送消息
/// <summary>
/// 发送消息
/// </summary>
/// <param name="groupIdentify"></param>
public void SendMsg(ChatMsgParamMainInfo content)
{
try
{
sendMsgToClient(content);
}
catch (Exception ex)
{
StringBuilder itemS = new StringBuilder();
itemS.AppendLine("发送消息异常:" + ex.Message);
LogHelper.Error(itemS.ToString());
}
}
#endregion
/// <summary>
/// 发送消息给用户
/// </summary>
private void sendMsgToClient(ChatMsgParamMainInfo content)
{
string senderConnectionId = Context.ConnectionId;
string senderNickName = "";
string senderHeadUrl = "";
var recevierInfo = userHubMain.Where(q => q.ConnectionId == Context.ConnectionId);
if (recevierInfo.Any())
{
senderNickName = recevierInfo.FirstOrDefault().NickName;
senderHeadUrl = recevierInfo.FirstOrDefault().HeadUrl;
}
var msgContent = new
{
senderConnectionId = senderConnectionId,
senderNickName = senderNickName,
senderHeadUrl = senderHeadUrl,
msgType = content.MsgType,
text = content.Text,
imgUrl = content.ImgUrl
};
Clients.Client(content.ReceiverConnectionId).acceptMsgToClient(msgContent);
}
}
/// <summary>
/// 建立链接实体对象
/// </summary>
public class UserChatIdentifyMainInfo
{
/// <summary>
/// 客户端推送消息链接Id
/// </summary>
public string ConnectionId { get; set; }
/// <summary>
/// 聊天昵称
/// </summary>
public string NickName { get; set; }
/// <summary>
/// 聊天头像
/// </summary>
public string HeadUrl { get; set; }
}
/// <summary>
/// 聊天实体对象
/// </summary>
public class ChatMsgParamMainInfo
{
/// <summary>
/// 接收者对象客户端Id(用来推送消息)
/// </summary>
public string ReceiverConnectionId { get; set; }
/// <summary>
/// 消息类型(0:文字 1:图片)
/// </summary>
public int MsgType { get; set; }
/// <summary>
/// 文字内容
/// </summary>
public string Text { get; set; }
/// <summary>
/// 图片Url
/// </summary>
public string ImgUrl { get; set; }
}
2. js代码
signalr建立与后台连接
var chat = $.connection.hubMain;
//客户端账号离线通知
$.connection.hubMain.client.noticeClientOnDisconnected = function (connectionId) {
//针对离线的用户进行逻辑处理,标识为离线状态...
};
//客户端账号上线通知
$.connection.hubMain.client.noticeClientOnLine = function (clientInfo) {
//加载新用户到菜单列表中...
};
//接收新消息
$.connection.hubMain.client.acceptMsgToClient = function (content) {
//处理新消息,写自己逻辑...
};
$.connection.hub.start().done(function () {
chat.server.initConnection();
}).fail(function () {
console.log('连接失败');
});
html页面不做展现,写个简单页面就可以