SignalR消息推送(03)

目录:

  • SignalR概念
  • 基本使用
  • 对点聊天

1.SignalR

是微软为实现实时通信而开发的一个类库。可进行分布式实时通信,远程代理实现。

1.1 两大内部对象

  • Persisten Connection

    用于客户端和服务器端的持久连接。

  • Hub(集线器)对象

    用于信息交互,将服务器端的数据推送(push)至客户端。

原理:客端建立与服端的连接。客端调用服端的方法。服端通过客端发送的请求,响应数据,调用客端的方法将数据推送至客端。

1.2 基本使用

  • 创建一个MVC应用程序。
  • 在MVC项目的Models文件夹中添加新项 SignalR Hub集线器类。
在创建的Hub类中添加如下代码:

//hub别名,方便前台调用
[HubName("getMsg")]
public class MyHub : Hub
{
public void Send(string title,string msg)
{
//调用客户端的sendMessage()方法
Clients.All.sendMessage(title,msg);  //其中Clients.All是dynamic类型,sendMessaage()方法是视图中js定义的function。
}
}
  • 在项目中添加 OWIN StartUp 类。
public class Startup
{
public void Configuration(IAppBuilder app)
{
//注册管道,使用默认的虚拟地址,根目录下的"/signalr",
//当然你也可以自己定义
app.MapSignalR();
}
}
  • 创建控制器和视图
//创建MessageController,并创建两个用于显示视图的action。
//控制器代码:
ublic class MessageController : Controller
{
//发送消息
public ActionResult SendMessage()
{
return View();
}
//接收消息
public ActionResult ReceiveMessage()
{
return View();
}
}

//发送消息视图代码:
<h2>发送消息</h2>
<div>
标题:<input type="text" id="title" />
</div><br />
<div>
内容:<textarea id="message" rows="4" cols="30"></textarea>
</div>
<br />
<div>
<input type="button" id="sendmessage" value="发送" />
</div>

<script src="~/Scripts/jquery.signalR-2.2.2.js"></script>
<!--引用自动生成的SignalR 集线器(Hub)脚本.在运行的时候在浏览器的Source下可看到 -->
<script src="~/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// 引用自动生成的集线器代理(此处使用别名getMsg)
var chat = $.connection.getMsg;
// 集成器连接开始
$.connection.hub.start().done(function () {
// 服务连接完成,给发送按钮注册单击事件
$('#sendmessage').click(function () {
// 调用服务器端集线器的Send方法
chat.server.send($("#title").val(), $('#message').val());  //又调用了客户端,客户端的函数就是添加信息列,就实现了广播消息功能
});
});
});
</script>

//接收消息视图代码:
<h2>接收消息</h2>
<div>
<br />
<div id="msgcontent"></div>
</div>
<script src="~/Scripts/jquery.signalR-2.2.2.js"></script>
<script src="~/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// 引用自动生成的集线器代理
var chat = $.connection.getMsg;
// 定义服务器端调用的客户端sendMessage来显示新消息
chat.client.sendMessage = function (title, message) {
// 向页面发送接收的消息
var html = "<div>标题:" + title + "消息内容:" + message + "</div>";
$("#msgcontent").after(html);
};
// 集成器连接开始
$.connection.hub.start(); //与SignalR服务建立连接
});
</script>

//<!--引用SignalR库. -->

<!--引用SignalR库. -->

<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>

<!--引用自动生成的SignalR 集线器(Hub)脚本 -->

<script src="~/signalr/hubs"></script>

1.3 实现点对点聊天

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会每一个客户端分配一个ConnnectionId

实现思路:

  • 客户端登入的时候记录下客户端的ConnnectionId,并将用户加入到一个静态数组中,该数据为了记录所有在线用户。
  • 用户可以点击在线用户中的用户聊天,在发送消息的时候,需要将ConnectionId一并传入到服务端。
  • 服务端根据传入的消息内容和ConnectionId调用Clients.Client(connnection).sendMessage方法来进行转发到对应的客户端。
[HubName("Chat")]
public class ChatHub : Hub
{
// 静态属性,在线用户列表
public static List<UserInfo> OnlineUsers = new List<UserInfo>();

//登录
public void Login(string userId,string userName)
{
//获取客户端的ConnectionId
var connnectId = Context.ConnectionId;
OnlineUsers.Add(new UserInfo
{
ConnectionId = connnectId,
UserId = userId,
UserName = userName
});
// 所有客户端同步在线用户
Clients.All.loadUser(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)
{
// 调用指定用户的客户端方法
Clients.Client(toUserId).receivePrivateMessage(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);
}
}


//客户端代码:
<h2>聊天系统</h2>
<div class="container">
@using (Html.BeginForm("login", "Chat", FormMethod.Post, new { @class = "form-inline" }))
{
<label>用户Id:</label>
@Html.TextBox("userId", "", new { @class = "form-control" })
<label>用户名:</label>
@Html.TextBox("userName", "", new { @class = "form-control" })
<input type="button" id="btnLogin" value="登录" class="btn btn-default" />
}
</div>
<hr />
<div class="container">
<div class="col-md-3">
<div class="panel panel-default">
<div class="panel-heading">
在线用户
</div>
<div class="panel-body">
<ul id="userList">
</ul>
</div>
</div>
</div>
<div class="col-md-8">
<div class="panel panel-default">
<div class="panel-heading">
聊天内容
</div>
<div class="panel-body">
<ul id="msgList" >
</ul>
</div>
<div class="panel-footer">
<label>消息To:</label> <label id="toUser"></label>
@Html.TextBox("msg", "", new { @class = "form-control form-inline" })
<input type="button" id="btnSend" value="发送" class="btn btn-default" />
</div>
</div>
</div>
</div>
@section scripts{
<script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
//用户点击(选择用户)
function selectUser(li) {
var connectionId = $(li).attr("cid");
$('#toUser').text(connectionId);
}
$(function () {
var chat = $.connection.Chat;

//刷新在线列表
chat.client.loadUser = function (allUsers) {
$('#userList').html("");
for (var i = 0; i < allUsers.length; i++) {
var li = $('<li cid="' + allUsers[i].ConnectionId+'" onclick="selectUser(this)">' + allUsers[i].UserId + ':' + allUsers[i].UserName + '</li> ');
$('#userList').append(li);
}
}
//接收消息
chat.client.receivePrivateMessage = function (from, msg) {
var li = $("<li>来自:" + from + "<br/>" + msg + "</li>");
$("#msgList").append(li);
}
 
$.connection.hub.start().done(function () {
console.log("连接完成");
//登录
$('#btnLogin').click(function () {
chat.server.login($("#userId").val(), $('#userName').val())
})


$('#btnSend').click(function () {
chat.server.sendPrivateMessage($('#toUser').text(), $('#msg').val())
})
});
})
</script>
实现
原文地址:https://www.cnblogs.com/shishixiang/p/14035227.html