SignalR 的Hub 提供了群组机制,可以把用户放到某一个或者多个组中,然后针对组进行消息推送。客户端和组之间是多对多的关系
Hub 的Groups 属性是IGroupManager 类型的,它有两个方法:
Add(string connectionId, string groupName)、
Remove(string connectionId, string groupName)
以上两个方法分别是根据connectionId 把连接加入或者从某个组移除。组的名字自定义,如果之前不存在这个组,会自动创建一个组,因此不需要单独创建组,相同groupName 为一组的。建议在OnDisconnected()中调用Remove 来移除组。
Hub 的Clients 属性是IHubCallerConnectionContext<dynamic> 类型的、
IHubCallerConnectionContext 又继承了IHubConnectionContext。所有的成员几乎都是dynamic 类
型的,所以怎么操作都可以。主要成员有:
1>
Caller
当前连接的客户端,可以通过Caller.aaa();直接调用浏览器端的function
2>
Others
,除了当前连接外的其他客户端
3>
OthersInGroup(string groupName)
名字为groupName 的组的所有成员。
4>
OthersInGroups(IList<string> groupNames)
在groupNames 这些组中的所有成员
5>
All
:所有连接的客户端
6>
AllExcept(params string[] excludeConnectionIds)
除了指定的多个ConnectionId 之外的其他
客户端
7>
Client(string connectionId)
指定的ConnectionId 对应的客户端
8>
Clients(IList<string> connectionIds)
指定的多个ConnectionId 对应的客户端
9>
Group(string groupName, params string[] excludeConnectionIds)
组groupName 中除了excludeConnectionIds 之外的客户端
10>
Groups(IList<string> groupNames, params string[] excludeConnectionIds)
组groupNames中除了excludeConnectionIds 之外的客户端
这些成员的返回值都是dynamic 类型的,有的对应一个客户端,有的对应多个客户端,无论对应几个,直接通过dynamic 调用通过Clients.All.onMessage(“hello”)这样方式通知到所有相关的客户端的js function 中。
Hub端
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
namespace SignalRApp
{
public class MyHub : Hub
{
这个方法名字是自定义的。参数也是自定义的
//public void SendMessage(string name, string msg)
//{
// //All表示监听所有连接上来的客户端。
// //onMessage是一个动态的方法,名字我们可以随意定的。这里我仅仅是给他取名叫onMessage而已,我们也可以叫Clients.All.ABC();
// Clients.All.onMessage(name + "和大家说:" + msg);//调用所有连接上来的客户端(包括自己)监听的onMessage事件。All是一个dynamic属性,所以可以随意的监听
// var clientConnectionId = Context.ConnectionId; //这是与我连接的客户端的连接ID(浏览器端)
// //我们还可以利用QueryString类接收数据
// string userName = Context.QueryString["userName"];
// string password = Context.QueryString["password"];
//}
//加入组
public void AddGroup(string groupName)
{
Groups.Add(this.Context.ConnectionId, groupName);//将此次连接的客户端(浏览器端)加入指定的组中
}
//向指定的组发送消息
public void SendGroupMsg(string groupName,string msg)
{
//向指定组中(除了我之外的成员)发送消息(这个我是指此次连接上hub的客户端)
Clients.OthersInGroup(groupName).onMessage(msg);
}
//重写父类OnConnected方法 :客户端连接上的时候会调用此方法
public override Task OnConnected()
{
return base.OnConnected();
}
//重写父类OnDisconnected方法 :OnConnected方法客户端断开连接的时候会调用此方法
public override Task OnDisconnected(bool stopCalled)
{
return base.OnDisconnected(stopCalled);
}
//重写父类OnReconnected方法 : 客户端可能网络不稳定,造成重新连接,就会调用此方法
//注意:客户端(浏览器页面)在刷新的时候不属于重连接,刷新是属于先断开连接,然后再连接
public override Task OnReconnected()
{
return base.OnReconnected();
}
}
}
客户端
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.signalR-2.1.2.js"></script>
<script src="/signalr/hubs" type="text/javascript"></script> <!--这是一个由 SignalR 处理的路径-->
</head>
<body>
<div>
<span>请选择要加入的组名:</span>
<select id="AddCityGroup">
<option>北京</option>
<option>上海</option>
<option>深圳</option>
<option>广州</option>
</select>
<input type="button" value="加入组" id="addgroup"/><div style="padding-bottom:50px"></div>
<div>以下是向选定的组发送消息内容:</div>
<span>请选择要发送消息的组名:</span>
<select id="CityGroup">
<option>北京</option>
<option>上海</option>
<option>深圳</option>
<option>广州</option>
</select>
<input type="text" id="msg" />
<input type="button" id="btn1" value="发送消息" />
</div>
<script type="text/javascript">
$(function () {
$.connection.myHub.client.onMessage = function (msg) { //注意,这一步一定要在 $.connection.hub.start()之前执行
alert("收到服务端发来的消息:" + msg)
}
//$.connection.hub.qs = { userName: "张三", password: "123456" };
$.connection.hub.start().done(function () {
alert("连接MyHub成功");
}).fail(function () { alert("连接MyHub失败") });
//加入组
$("#addgroup").click(function () {
var groupName = $('#AddCityGroup option:selected').text();
$.connection.myHub.server.addGroup(groupName);//这个页面是客户端,运行Index.cshtml页面的时候,会执行这个script代码块,它会向外面指定的MyHub服务发起连接,每个连接都有一个单独的连接id,然后它会请求Myhub类中的AddGroup方法。(注意方法名的第一个字母必须小写,即便服务中的方法名是大写的)
})
//向指定组发送消息
$("#btn1").click(function () {
//注意:不管项目中声明的SignalR集线器类的中的方法名字的首字母是大写还是小写,这的名字都必须是小写开头
//例如:我的SignalR集线器类的名字叫MyHub.cs 它里面声明了一个SendMessage方法,这里必须写成sendMessage
//$.connection.myHub.server.sendMessage("小米", "我上市啦"); //向服务端发送消息
var groupName = $('#CityGroup option:selected').text();
var msg = $("#msg").val();
$.connection.myHub.server.sendGroupMsg(groupName, msg);//向指定的组中发送消息
})
})
</script>
</body>
</html>
测试:开几个浏览器窗口