工做上遇到一個推送消息的功能的實現。本着面向百度編程的思想。網上百度了一大堆。主要的實現方式是原生的WebSocket,和SignalR。javascript
這裏簡單的介紹一下Signalr,SignalR 封裝了WebSocket、ForeverFrame、ServerSentEvents、LongPolling四種主要的傳輸協議。兼容性比較好,WebSocket 是有要求的,IIS服務須要系統是Win8或者 Server 2012 以上。下面開始擼代碼。html
1.首先創建一個項目。前端
2.經過包管理工具,引入SignalR java
3.引入以後,須要手動添加兩個類。jquery
PushHub 集線器類,Singlarl類的主要操做都由這個類實現。git
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類github
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.前臺代碼app
<!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的代碼ide
demo代碼:https://github.com/chaorending/Demo.SignalR.git