Asp.Net SignalR 使用记录
工作上遇到一个推送消息的功能的实现。本着面向百度编程的思想。网上百度了一大堆。主要的实现方式是原生的WebSocket,和SignalR。
这里简单的介绍一下Signalr,SignalR 封装了WebSocket、ForeverFrame、ServerSentEvents、LongPolling四种主要的传输协议。兼容性比较好,WebSocket 是有要求的,IIS服务需要系统是Win8或者 Server 2012 以上。下面开始撸代码。
1.首先建立一个项目。

2.通过包管理工具,引入SignalR

3.引入之后,需要手动添加两个类。
PushHub 集线器类,Singlarl类的主要操作都由这个类实现。
1 public class PushHub : Hub
2 {
3 /// <summary>
4 /// 第一次连接
5 /// </summary>
6 /// <returns></returns>
7 public override Task OnConnected()
8 {
9 return base.OnConnected();
10 }
11
12 /// <summary>
13 /// 断开连接
14 /// </summary>
15 /// <param name="stopCalled"></param>
16 /// <returns></returns>
17 public override Task OnDisconnected(bool stopCalled)
18 {
19 string user = ConnectManager.GetUserName(Context.ConnectionId);
20 ConnectManager.RemoveUser(user);
21 Show(string.Format("{0}退出", user));
22
23 return base.OnDisconnected(stopCalled);
24 }
25
26 /// <summary>
27 /// 获取当前的用户标识
28 /// </summary>
29 /// <returns></returns>
30 private string GetUserId()
31 {
32 return Context.QueryString["userId"];
33 }
34
35 /// <summary>
36 /// 发送消息
37 /// </summary>
38 /// <param name="content"></param>
39 /// <param name="receiveUser"></param>
40 public void Show(string content,string receiveUser="")
41 {
42 string user = ConnectManager.GetUserName(Context.ConnectionId);
43 if (string.IsNullOrEmpty(receiveUser))
44 {
45 Clients.All.show(content);
46 }
47 else {
48 Clients.Client(ConnectManager.GetUserConnect(receiveUser)).show(string.Format("{0}发消息:{1}",user, content));
49 }
50
51 }
52
53 /// <summary>
54 /// 登录操作
55 /// </summary>
56 /// <param name="user"></param>
57 public void Login(string user)
58 {
59
60 ConnectManager.OnlineInit(user, Context.ConnectionId);
61 Show(string.Format("{0}:登录成功", user));
62 }
63
64 }
4.Startup类

public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR(); //声明注册集线器映射
}
}
5.连接管理类
1 /// <summary>
2 /// 连接管理类
3 /// </summary>
4 public class ConnectManager
5 {
6 /// <summary>
7 /// 连接记录池
8 /// </summary>
9 private readonly static ConcurrentDictionary<string, string> _connectPool = new ConcurrentDictionary<string, string>();
10
11 /// <summary>
12 /// 添加用户
13 /// </summary>
14 /// <param name="userKey"></param>
15 /// <param name="connection"></param>
16 public static void AddUser(string userKey, string connection)
17 {
18 _connectPool[userKey] = connection;
19 }
20
21 /// <summary>
22 /// 删除用户
23 /// </summary>
24 /// <param name="userKey"></param>
25 public static void RemoveUser(string userKey)
26 {
27 string connection = null;
28 _connectPool.TryRemove(userKey, out connection);
29 }
30
31 /// <summary>
32 /// 是否存在连接(是否在线)
33 /// </summary>
34 /// <param name="receiverId"></param>
35 /// <returns></returns>
36 public static bool IsOnline(string receiverId)
37 {
38 return _connectPool.Keys.Contains(receiverId);
39 }
40
41 /// <summary>
42 /// 推送消息给个人
43 /// </summary>
44 /// <param name="receiveId"></param>
45 /// <param name="msg"></param>
46 public static void PushSingleMessage(string receiveId, string msg)
47 {
48 try
49 {
50 GetHubContext().Clients.Client(_connectPool[receiveId]).show(msg);
51 }
52 catch (Exception ex)
53 {
54 var errMsg = ex.Message;
55 }
56 }
57
58 /// <summary>
59 /// 获取推送上下文
60 /// </summary>
61 /// <returns></returns>
62 public static IHubContext GetHubContext()
63 {
64 return GlobalHost.ConnectionManager.GetHubContext<PushHub>();
65 }
66
67 /// <summary>
68 /// 上线初始化
69 /// </summary>
70 /// <param name="userId">用户ID</param>
71 /// <param name="connectionId">连接ID</param>
72 public static void OnlineInit(string userId, string connectionId)
73 {
74 AddUser(userId, connectionId);
75 }
76
77 public static string GetUserName(string value)
78 {
79 return _connectPool.Where(a => a.Value == value).FirstOrDefault().Key;
80 }
81
82 public static string GetUserConnect(string userName)
83 {
84 return _connectPool[userName];
85 }
86 }
6.前台代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div>
用户名称:<input type="text" id="user" placeholder="输入用户名" class="input" /><input type="button" id="login" value="登录" class="btn btn-sm btn-info" /><br />
接收人:<input type="text" id="receiveUser" placeholder="接收人(不填默认群发)" class="input" /><br />
<input type="text" id="content" placeholder="发送内容" class="input" /> <input type="button" value="发送" class="btn btn-sm btn-info" id="send" />
<div>
<h4>接收到的信息:</h4>
<ul id="dataContainer"></ul>
</div>
</div>
<script src="Scripts/jquery-3.3.1.min.js"></script>
<script src="Scripts/jquery.signalR-2.4.1.min.js"></script>
<script src="signalr/hubs"></script> ///这个要注意默认就是这样写,不要问为什么。哈哈
<script language="javascript">
$(function () {
var chat = $.connection.pushHub;
console.log(chat);
//连接服务端集线器,demoHub为服务端集线器名称,js上首字母须改为小写(系统默认)
//定义客户端方法,此客户端方法必须与服务端集线器中的方法名称、参数均一致。
//实际上是服务端调用了前端的js方法(订阅)
//若多个参数,服务端也需要一致
chat.client.show = function (content) {
var html = '<li>' + htmlEncode(content) + "</li>";
$("#dataContainer").append(html);
}
//定义推送
$.connection.hub.start()
.done(function () {
$("#login").click(function () {
chat.server.login($("#user").val()); //将客户端的content内容发送到服务端
$("#user").val("");
});
$("#send").click(function () {
chat.server.show($("#content").val(), $("#receiveUser").val()); //将客户端的content内容发送到服务端
$("#content").val("");
});
});
});
//编码
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
</body>
</html>
这就是所有的demo的代码
demo代码:https://github.com/chaorending/Demo.SignalR.git

浙公网安备 33010602011771号