本文將使用一個NuGet公開的組件技術來實現數據訂閱推送功能,由服務器進行推送數據,客戶端訂閱指定的數據後,便可以接收服務器推送過來的數據,包含了自動重連功能,使用很是方便css
nuget地址:https://www.nuget.org/packages/HslCommunication/ html
github地址:https://github.com/dathlin/HslCommunication 若是喜歡能夠star或是fork,還能夠打賞支持。java
聯繫做者及加羣方式(激活碼在羣裏發放):http://www.hslcommunication.cn/Cooperationpython
在Visual Studio 中的NuGet管理器中能夠下載安裝,也能夠直接在NuGet控制檯輸入下面的指令安裝:git
Install-Package HslCommunication
NuGet安裝教程 http://www.cnblogs.com/dathlin/p/7705014.htmlgithub
下面的一個項目是這個組件的訪問測試項目,您能夠進行初步的訪問的測試,免去了您寫測試程序的麻煩,源代碼也在本文開始處的項目裏,數據庫
下載地址爲:HslCommunicationDemo.zip json
如下就是對服務器的指定關鍵字的數據的訂閱,服務器提供了幾個關鍵字訂閱,以供測試。安全
若是該服務器不可用,請下載本地版本的服務器服務器
ModBus組件全部的功能類都在 HslCommunication.Enthernet 命名空間,因此再使用以前先添加
using HslCommunication.Enthernet; using HslCommunication;
先進行聲明變量
private NetPushServer pushServer;
而後再一個啓動按鈕裏寫上以下的代碼
pushServer = new NetPushServer( ); pushServer.ServerStart( 12345 );
到這裏爲止,服務器的代碼基本已經寫好了,短短的兩三行代碼而已。只是目前的數據並無數據推送功能。
一個經典的情景是什麼,好比你有一堆實時數據是從設備採集回來的,這些數據是在服務器上的。 你還有個客戶端的軟件,不少人同時在線,若是別人打開監控實時數據的話,就特別適用於本組件的方法,由於你走數據庫顯然是更慢的,並且對服務器壓力也大。採用本組件就能夠完美的解決這件事情、
假設你採集了來自設備的數據,咱們作個1秒鐘的定時器,而後啓動定時器,模擬每秒鐘的數據推送,推送什麼呢?先試試看隨機數
private Random random = new Random( ); // 先定義一個隨機數生成器
定時器的代碼以下:
pushServer.PushString( "A", random.Next( 1000, 10000 ).ToString( ) );
到這裏爲止,服務器的一個完整的代碼已經寫完了。咱們來看看客戶端怎麼寫
先進行聲明變量
private NetPushClient pushClient;
實例化,須要指定服務器的IP和端口,還有想訂閱的關鍵字
pushClient = new NetPushClient( "127.0.0.1", 12345, "A" );
接下來就是建立訂閱了,須要指定一個調用的委託,會返回一個是否成功的信號,由於有可能網絡的緣由,有可能由於沒有這個關鍵字,會致使建立失敗。
OperateResult create = pushClient.CreatePush( new Action<NetPushClient, string>( PushFromServer ) ); if (create.IsSuccess) { MessageBox.Show( "成功" ); } else { MessageBox.Show( "失敗:" + create.Message ); }
上面使用了一個委託,PushFromServer的方法以下,主要是使用委託把數據顯示出來:
private void PushFromServer( NetPushClient pushClient, string data ) { if (IsHandleCreated) Invoke( new Action<string>( m => { label8.Text = DateTime.Now.ToString( "yyyy-MM-dd HH:mm:ss.fff" ); // 顯示接收時間 receiveCount++; label9.Text = receiveCount.ToString( ); // 顯示接收次數 textBox4.Text = m; // 數據最終顯示在這裏 } ), data ); }
在相應的窗口關閉以前,關閉掉客戶端就能夠了。若是不手動關閉,當你關閉窗口的時候,該鏈接頗有可能仍然存在。
pushClient.ClosePush( );
一個簡單的完整的數據訂閱功能已經完成了。
上面的代碼只能推送字符串數據,怎麼樣實現推送複雜的數據呢,咱們假設有4個數據,須要同時推送給客戶端。那咱們能夠選擇2種方式,一種是json,一種是xml,各有優缺點
JSON
JObject json = new JObject( ); json.Add( "value1", new JValue( random.Next( 1000, 9999 ) ) ); json.Add( "value2", new JValue( Math.Round( random.NextDouble( ), 6 ) * 1000 )); json.Add( "value3", new JValue( Guid.NewGuid( ).ToString( ) ) ); json.Add( "value4", new JValue( DateTime.Now ) ); pushServer.PushString( textBox14.Text, json.ToString( ) );
Xml
XElement element = new XElement( "Data" ); element.SetElementValue( "value1", random.Next( 1000, 9999 ) ); element.SetElementValue( "value2", (Math.Round( random.NextDouble( ), 6 ) * 1000 ).ToString() ); element.SetElementValue( "value3", Guid.NewGuid( ).ToString( ) ); element.SetElementValue( "value4", DateTime.Now.ToString( "O" ) ); pushServer.PushString( textBox18.Text, element.ToString( ) );
解析的時候按照對應的信息解析便可。
服務器支持令牌設置,若是客戶端沒法提供一致的令牌校驗,就會被拒絕鏈接,提高系統的安全性
pushServer.Token = new Guid( "04f6e588-4b9c-4dfb-86b2-4389742534b5" );
客戶端就須要設置相同的令牌才能登錄服務器,從而進行數據校驗。
pushServer.LogNet = new HslCommunication.LogNet.LogNetSingle( "log.txt" ); // 支持日誌
有一個屬性是標識服務器端在線的全部客戶端的數量,方便的系統進行監控
pushServer.OnlineCount
上面演示的都是手動推送的服務器數據,或是寫代碼採集設備來實現自動推送,若是想作分佈式的數據推送,或是緩解服務器的數據推送,那麼能夠按照以下作
就是說,由一個主服務器將數據推到2個子服務器,再由子服務器將數據推送給客戶端
對於主服務和推送客戶端代碼不須要任何改變,主要是加一層中間服務器,也是NetPushServer類,子服務器的數據須要來自手動,只須要手動加一行代碼便可
OperateResult create = pushServer.CreatePushRemote( "127.0.0.1", 12345, "A" ); if(create.IsSuccess) { MessageBox.Show( "建立成功!" ); } else { MessageBox.Show( "建立失敗!" + create.Message ); }
意思就是這個子服務器訂閱了另外一個主服務器的關鍵字A的數據,並實時推給了其餘在線的客戶端。
熟悉這個原理後,就能夠構建一個高性能的數據推送網絡服務。
以上的操做都是靜態的關鍵字推送,推送的數據都是你們都有的,如何推送一個專門的客戶端呢?也能夠實現,稍微複雜一點,先經過另外一個網絡來約定一個共同的惟一的關鍵字,好比GUID碼,而後已這個碼做爲關鍵字推送。
另外一種交互網絡能夠參考:http://www.cnblogs.com/dathlin/p/7697782.html
這種狀況適用什麼例子呢,,,,好比你向服務器弄了個請求,這個請求可能好久,你也不知道服務器何時能完成,須要一個百分比顯示服務器進度的時候,就須要動態關鍵字了,服務器操做的過程只須要向惟一的關鍵字推送進度便可。
若是有什麼問題,能夠加羣聊。