好久都沒有寫博客了,從15年4月份一直忙到如今,我纔有時間去作梳理和總結,由於我提離職了,感受整個世界忽然變得不同,隨着而來的就是心情的放鬆,寫一篇文章也是對過去一年多工做的梳理,加深印象 積累和沉澱。web
由於從事的公司是建築行業的公司,產品也是基於建築管理體系,總體的項目包含了web端、客戶端、服務端,以及由於產品功能須要的一些工具類的軟件。在這種多系統的體系結構之下,咱們須要進行多個系統之間的實時通信,其實作到實時通信的方式有不少種sql
1.sql server的Server_borker 數據變動通知,是基於sql server數據庫的,表中的數據變動會通知到監聽的那端,可是以爲考慮到通信比較頻繁,通信端比較多,這種方式很容易形成代碼上和程序上的混亂,不作考慮。數據庫
2.wcf的消息廣播 相比第一種,這個對於這種多系統通信更加不具有優點。這種在服務端進行操做,客戶端經過註冊來監聽服務端處理的進度很明顯不適合兩個或者多個客戶端之間的通訊,咱們的系統可不只僅限於客戶端服務端這麼簡單,不作考慮。服務器
3..NetMQ 就是本章中要介紹的解決多系統通信問題的殺手鐗了。這個其實在最開始是咱們同事去下載研究的,在以後通過一些包裝能夠很方便的去使用,接下來咱們去一塊兒瞭解一下。app
下載地址:http://www.codeproject.com/Articles/193611/DotNetMQ-A-Complete-Message-Queue-System-for-NETide
簡單的畫個圖能夠更加方便的去了解這個結構工具
經過這個圖咱們能夠看到,在多個客戶端通信以前須要先開啓服務,而後經過惟一性的token咱們就能夠作到客戶端之間的信息通信。加密
下載下來的應該是一個服務的啓動程序和一個管理端,通過包裝和更改更加方便使用一些:spa
兩個服務code
1..NETMQ自己的服務
2.添加令牌的服務,開放成對外的wcf接口,能夠經過接口取添加令牌。
關於服務配置其實修改後只須要服務端口就好了,鏈接經過地址和端口號就能夠鏈接。
最後就是令牌了,令牌就是客戶端之間通信的一個token,就是一個惟一的識別信息,就跟qq同樣,給妹子發信息總要知道人家的qq號吧,token其實也能夠這麼理解。
客戶端上線以後就客戶端鏈接就是1。
經過上述的描述我想基本都對這個有一個印象了,經過這些印象咱們能夠想象到他的應用場景,好比去作一個聊天工具,作上傳下載的進度提示,等等。
瞭解了應用場景咱們就應該去想一想咱們怎麼樣才能簡單而又方便的把它應用在咱們的項目中,能夠解決咱們產品和項目中的實際問題。
服務端:
圖中能夠看到,咱們下載下來的.NETMQ在服務端只須要引用這三個庫就能夠了,
MQServer就是咱們針對實際項目應用作的一些修改,將服務開啓、中止、令牌的添加刪除以及管理都在這裏作了包裝,只須要去引用就能夠了。
/// <summary> /// 消息中心服務器端管理類 /// </summary> public class MQService { #region 單例 private static MQService _instance; /// <summary> /// 單例 /// </summary> public static MQService Instance { get { if (_instance == null) { _instance = new MQService(); } return _instance; } } #endregion #region 字段 MDSServer server; MDSController controller; #endregion #region 屬性 /// <summary> /// 服務是否處於開啓狀態 /// </summary> public bool IsOpened { get; set; } #endregion #region 構造方法 public MQService() { server = new MDSServer(); } #endregion #region 開啓服務 /// <summary> /// 開啓服務 /// </summary> public void Start() { try { server.Start(); IsOpened = true; controller = new MDS.Management.MDSController(AppConfig.Config.MessageServiceIP, AppConfig.Config.MessageServicePort); controller.Connect(); } catch (Exception ex) { throw ex; } } #endregion #region 關閉服務 /// <summary> /// 關閉服務 /// </summary> public void Stop() { try { if (IsOpened) { server.Stop(true); IsOpened = false; controller.Disconnect(); } } catch (Exception ex) { throw ex; } } #endregion #region 添加令牌 public bool AddToken(string token) { try { controller.SendMessage( new AddNewApplicationMessage { ApplicationName = token }); return true; } catch { return false; } } #endregion #region 刪除令牌 public void RemoveToken(string token) { var message = controller.SendMessageAndGetResponse( new RemoveApplicationMessage { ApplicationName = token }); } #endregion #region 獲取令牌列表 public ObservableCollection<TokenClass> GetTokenList() { ObservableCollection<TokenClass> result = new ObservableCollection<TokenClass>(); //Send a message to MDS server to get list of client applications, get response and fill data grid. var message = controller.SendMessageAndGetResponse(new GetApplicationListMessage()); if (message.MessageTypeId != ControlMessageFactory.MessageTypeIdGetApplicationListResponseMessage) { throw new MDSException("Response message to GetApplicationListMessage must be a GetApplicationListResponseMessage"); } var applicationListMessage = message as GetApplicationListResponseMessage; if (applicationListMessage == null) { throw new MDSException("Incorrect message type. MessageTypeId = " + message.MessageTypeId + ", but Type of object: " + message.GetType().Name); } MDS.Communication.Messages.ControllerMessages.GetApplicationListResponseMessage.ClientApplicationInfo[] applications = applicationListMessage.ClientApplications; foreach (var application in applications) { TokenClass tc = new TokenClass(); tc.TokenName = application.Name; tc.TokenConnect = application.CommunicatorCount; result.Add(tc); } return result; } #endregion }
服務端簡單的使用就是這些,詳細的介紹以及內部原理網上不少,這裏就不介紹了。
客戶端:
關於客戶端呢,爲了便於更方便的使用我寫一個簡單的demo去演示一下。
圖中紅框的部分其實就是MDSCommonLib這個庫,下面幾個類就是對外的事件和方法的包裝,咱們能夠看一下代碼:
public class MQMessage { CommunicationClient client; public readonly static MQMessage Instance = new MQMessage(); public MQMessage() { //FileTransfer.BLL.XmlReader.ReadXmlInfo(); client = new CommunicationClient(); client.OnMessageReceived += client_OnMessageReceived; client.OnResponseMessageReceived += client_OnResponseMessageReceived; } /// <summary> /// 接收消息事件 /// </summary> public event EventHandler OnMessageReceived; /// <summary> /// 接收消息回執事件 /// </summary> public event EventHandler OnResponseMessageReceived; /// <summary> /// 接收消息事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void client_OnResponseMessageReceived(object sender, MessageReceiveEventArgs e) { if (OnResponseMessageReceived != null) { OnResponseMessageReceived(sender, e); } } /// <summary> /// 接收消息回執事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void client_OnMessageReceived(object sender, MessageReceiveEventArgs e) { if (OnMessageReceived != null) { OnMessageReceived(sender, e); } } /// <summary> /// 發送消息 /// </summary> /// <param name="messageContent"></param> public void SendMessage(string messageContent, string tokenName) { client.SendMessage(messageContent, tokenName); } /// <summary> /// 開啓服務 /// </summary> public void Start(string tokenName) { client.StartConnection("127.0.0.1", 10905, tokenName); } /// <summary> /// 關閉服務 /// </summary> public void Stop() { client.StopConnection(); } }
這是最外層的包裝,經過這些就能夠去調用
MQClientLib.MQMessage.Instance.Start("User_Sean");
客戶端開啓鏈接的方式僅僅這樣就能夠了,經過這行表示:User_Sean上線了。
這樣咱們在服務端就能夠看到User_Sean的鏈接:
吶,這是一個客戶端,若是是多個客戶端鏈接上了呢? 咱們就能夠經過
/// <summary> /// 發送消息 /// </summary> /// <param name="messageContent"></param> public void SendMessage(string messageContent, string tokenName) { client.SendMessage(messageContent, tokenName); }
調用這行代碼去向其它客戶端發送信息,其它客戶端接收到信息的時候也會觸發這邊的回執事件。
/// <summary> /// 接收消息回執事件 /// </summary> public event EventHandler OnResponseMessageReceived;
經過註冊這個事件,在對方接收到你發送的消息的時候,能夠觸發這個事件。
/// <summary>
/// 接收消息事件
/// </summary>
public event EventHandler OnMessageReceived;
這個是用來接收別人給你發送的信息的,信息經過這個時間的sender傳遞過來。
使用暫時就這些,由於代碼是加密的,因此只能之後去從新作一下而後給各位提供下載地址了。
固然,關於mq的使用dotNetMQ只是其中一項,今天介紹的也只是通信,以後下一篇博客會介紹相關的msmq、queue等等,後面精彩繼續~~~~~