C# 網絡通訊功能 同步數據交互開發

前言


 本文將使用一個Nuget公開的組件技術來實現一對多的數據通訊功能,提供了一些簡單的API,來方便的向服務器進行數據請求。html

 

在visual studio 中的Nuget管理器中能夠下載安裝,也能夠直接在Nuget控制檯輸入下面的指令安裝:git

Install-Package HslCommunication

Nuget安裝教程  http://www.cnblogs.com/dathlin/p/7705014.htmlgithub

聯繫做者及加羣方式(激活碼在羣裏發放):http://www.hslcommunication.cn/Cooperation數組

 

 

Summary


 

一個用於同步數據交互的網絡通訊類,在實際的程序開發中,咱們常常會碰到這樣的須要,咱們須要向服務器請求一些數據,而後接收從服務器返回的數據,數據類型一般爲 byte[] 或是 string ,類型,因此一般在服務器端會配置一個數據處理總站,每次請求都會帶有一個信號頭,用於服務器區分不一樣的信息機制,而咱們可使用組件中的 NetSimplifyServerNetSimplifyClient 類來完成功能。安全

該通信類對全部的底層進行了封裝,包含了協議頭定義,令牌驗證,數據的加密解密,壓縮和解壓縮,能夠安全的在局域網和廣域網上進行數據傳播,服務器端還增長了防止惡意鏈接機制,有效抵制來自網絡的惡意網絡攻擊。服務器

 

Reference


 

日誌組件全部的功能類都在 HslCommunicationHslCommunication.Enthernet 命名空間,因此再使用以前先添加網絡

using HslCommunication;
using HslCommunication.Enthernet;

How to Use


 

服務器端

咱們先要在服務器端進行建立網絡監聽,這樣才能讓客戶端鏈接到服務器,服務器須要先實例化及初始化代碼以下,代碼直接在服務器主窗口下面:架構

// 用戶同步數據傳送的引擎
        private NetSimplifyServer net_simplify_server = new NetSimplifyServer(); //實例化
        // 同步傳送數據的初始化
        private void Net_Simplify_Server_Initialization()
        {
            try
            {
                net_simplify_server.KeyToken = Guid.Empty;//設置身份令牌,本質就是一個GUID碼,驗證客戶端使用
                net_simplify_server.LogNet = new LogNetSingle(LogSavePath + @"\simplify_log.txt");//日誌路徑,單文件存儲模式,採用組件信息
                net_simplify_server.LogNet.SetMessageDegree(HslMessageDegree.DEBUG);//默認debug及以上級別日誌均進行存儲,根據須要自行選擇,DEBUG存儲的信息比較多
                net_simplify_server.ReceiveStringEvent += Net_simplify_server_ReceiveStringEvent;//接收到字符串觸發
                net_simplify_server.ReceivedBytesEvent += Net_simplify_server_ReceivedBytesEvent;//接收到字節觸發
                net_simplify_server.ServerStart(17432);//網絡端口,此處使用了一個隨便填寫的端口
            }
            catch (Exception ex)
            {
                SoftBasic.ShowExceptionMessage(ex);
            }
        }

        /// <summary>
        /// 接收來自客戶端的字節數據
        /// </summary>
        /// <param name="state">網絡狀態</param>
        /// <param name="customer">字節數據,根據實際狀況選擇是否使用</param>
        /// <param name="data">來自客戶端的字節數據</param>
        private void Net_simplify_server_ReceivedBytesEvent(AsyncStateOne state, NetHandle customer, byte[] data)
        {
            if(customer==1000)
            {
				// 收到指令爲1000的請求時,返回1000長度的字節數組
                net_simplify_server.SendMessage(state, customer, new byte[1000]);
            }
            else
            {
                net_simplify_server.SendMessage(state, customer, data);
            }
        }




        /***********************************************************************************************
         * 
         *    方法說明:    當接收到來自客戶端的數據的時候觸發的方法
         *    特別注意:    若是你的數據處理中引起了異常,應用程序將會奔潰,SendMessage異常系統將會自動處理
         * 
         ************************************************************************************************/


        /// <summary>
        /// 接收到來自客戶端的字符串數據,而後將結果發送回客戶端,注意:必須回髮結果
        /// </summary>
        /// <param name="state">客戶端的地址</param>
        /// <param name="handle">用於自定義的指令頭,可不用,轉而使用data來區分</param>
        /// <param name="data">接收到的服務器的數據v/param>
        private void Net_simplify_server_ReceiveStringEvent(AsyncStateOne state, NetHandle handle, string data)
        {

            /*******************************************************************************************
             * 
             *     說明:同步消息處理總站,應該根據不一樣的消息設置分流到不一樣的處理方法
             *     
             *     注意:處理完成後必須調用 net_simplify_server.SendMessage(state, customer, "處理結果字符串,能夠爲空");
             *
             *******************************************************************************************/

            if (handle == 1)
            {
                net_simplify_server.SendMessage(state, handle, "測試數據一");
            }
            else if (handle == 2)
            {
                net_simplify_server.SendMessage(state, handle, "測試數據二");
            }
			else if (handle == 3)
            {
                net_simplify_server.SendMessage(state, handle, "測試數據三");
            }
            else
            {
// 這部分的代碼是必須的,即便你不作任何處理,也應該返回原數據 net_simplify_server.SendMessage(state, handle, data); } }

服務端的主要代碼都在上面的代碼段了,也沒多少代碼,關鍵是支持的請求多了以後,不停的使用 if...else 代碼會顯得不少很亂,因此此處的 Nethandle 這個值類型就是爲了解決這個問題而設計的,它本質上是一個 int 數據,咱們知道一個 int 是由4個字節組成,那麼byte[0]byte[1]byte[2]byte[3],那麼我能夠用byte[3](最高位)來做爲指令大類。byte[2]來做爲指令小類,byte[0]和byte[1]組成的 ushort 數據來做爲指令編號,因此上述的方法 Net_simplify_server_ReceiveStringEvent 中的細節能夠改爲下面:工具

        /// <summary>
        /// 接收到來自客戶端的字符串數據,而後將結果發送回客戶端,注意:必須回髮結果
        /// </summary>
        /// <param name="state">客戶端的地址</param>
        /// <param name="handle">用於自定義的指令頭,可不用,轉而使用data來區分</param>
        /// <param name="data">接收到的服務器的數據</param>
        private void Net_simplify_server_ReceiveStringEvent(AsyncStateOne state, NetHandle handle, string data)
        {

            /*******************************************************************************************
             * 
             *     說明:同步消息處理總站,應該根據不一樣的消息設置分流到不一樣的處理方法
             *     
             *     注意:處理完成後必須調用 net_simplify_server.SendMessage(state, customer, "處理結果字符串,能夠爲空");
             *
             *******************************************************************************************/

            if (handle.CodeMajor == 1)
            {
                ProcessCodeMajorOne(state, handle, data);
            }
            else if (handle.CodeMajor == 2)
            {
                ProcessCodeMajorTwo(state, handle, data);
            }
			else if (handle.CodeMajor == 3)
            {
                ProcessCodeMajorThree(state, handle, data);
            }
            else
            {
                net_simplify_server.SendMessage(state, handle, data);
            }
        }

        private vode ProcessCodeMajorOne(AsyncStateOne state, NetHandle handle, string data)
        {
            if (handle.CodeIdentifier == 1)
            {
                // 下面能夠再if..else
                net_simplify_server.SendMessage(state, handle, "測試數據大類1,命令1,接收到的數據是:" + data);
            }
            else
            {
                net_simplify_server.SendMessage(state, handle, data);
            }
        }

        private vode ProcessCodeMajorTwo(AsyncStateOne state, NetHandle handle, string data)
        {
            if (handle.CodeIdentifier == 1)
            {
                // 下面能夠再if..else
                net_simplify_server.SendMessage(state, handle, "測試數據大類2,命令1,接收到的數據是:" + data);
            }
            else
            {
                net_simplify_server.SendMessage(state, handle, data);
            }
        }

        private vode ProcessCodeMajorThree(AsyncStateOne state, NetHandle handle, string data)
        {
            if (handle.CodeIdentifier == 1)
            {
                // 下面能夠再if..else
                net_simplify_server.SendMessage(state, handle, "測試數據大類3,命令1,接收到的數據是:" + data);
            }
            else
            {
                net_simplify_server.SendMessage(state, handle, data);
            }
        }

  指令根據不一樣的功能進行歸類,會使代碼簡潔不少。oop

 

客戶端

客戶端的程序相對簡單不少,只須要實例化一下就可使用了,並且該實例化對象的方法是線程安全的,因此在定義成靜態對象,在代碼的任何地方均可以使用,不須要再重複實例化,以下代碼是實例化:

        // 用於訪問服務器數據的網絡對象類,必須修改這個端口參數,不然運行失敗
        public static NetSimplifyClient Net_simplify_client { get; set; } = new NetSimplifyClient(
            new IPEndPoint(IPAddress.Parse("127.0.0.1"), 17432))  // 指定服務器的ip,和服務器設置的端口
        {
            KeyToken = Guid.Empty, // 這個guid碼必需要服務器的一致,不然服務器會拒絕鏈接
            ConnectTimeout = 5000,// 鏈接的超時時間
        };

接下來就是讀取數據的展現了,返回的結果關聯到一個類 OperateResult<string> 這個類只包含了幾個公開的數據屬性,沒什麼實際的含義,一看就明白了。下面的代碼能夠放到button按鈕裏去測試

            OperateResult<string> result = Net_simplify_client.ReadFromServer(
                new NetHandle(1,0,1), "發送的數據"); // 指示了大類1,子類0,編號1

            if (result.IsSuccess)
            {
                // 按照上面服務器的代碼,此處顯示數據爲:"上傳成功!返回的數據:測試數據大類1,命令1,接收到的數據是:發送的數據"
                MessageBox.Show(result.Content);
            }
            else
            {
                MessageBox.Show("操做失敗!緣由:" + result.Message);// 失敗的緣由基本上是鏈接不上,若是GUID碼填寫錯誤,也會鏈接不上
            }

  

失敗說明

失敗的緣由一般來自網絡異常,當你把服務器架設在雲端時,或是其餘的服務器電腦,若是訪問總是失敗,就要檢查防火牆是否容許指定端口網絡通訊了。

 

Test Client


 測試工具,當你在服務器端架設好同步網絡的後臺代碼後,想要進行快速測試服務器的狀態是否正確的時候,能夠經過下面的組件來實現數據測試:

 測試工具在github上開源,屬於C-S架構模版的一部分,地址爲:

 https://github.com/dathlin/ClientServerProject

 必須帶有HslCommunication.dll和Newtonsoft.Json.dll組件放到一塊兒,這樣就能夠運行測試了:

首先先添加鏈接點:

接下來輸入鏈接信息,包括服務器的IP地址,同步網絡端口號,令牌信息

鏈接完成後,點擊下面圖片的1處,在2處會顯示固然鏈接的信息,而後在3處輸入指令,點擊4進行發送,就會顯示來自服務器的數據結果,如圖顯示返回了一個JOSN字符串信息:

相關文章
相關標籤/搜索