<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      IoTClient開發4 - ModBusTcp協議服務端模擬

      前言

      上篇我們實現了ModBusTcp協議的客戶端讀寫,可是在很多時候編寫業務代碼之前是沒有現場環境的。總不能在客戶現場去寫代碼,或是蒙著眼睛寫然后求神拜佛不出錯,又或是在辦公室部署一套硬件環境。怎么說都感覺不太合適,如果我們能用軟件仿真模擬硬件那不就完美了,以后有各種不同的硬件協議接口都模擬出來,而不是每個硬件都買一套回來部署了做測試。
      真要用軟件仿真模擬也是可以的,客戶端是對協議的請求報文發送和響應報文的解析,服務端其實就是請求報文的接收和響應報文的發送,正好和客戶端的動作相反。
      前面我們在寫你也可以寫個聊天程序 - C# Socket學習1的時候就有寫Socket服務端實現,其實這個也差不了多少。

      ModBusTcp報文分析(上篇拷貝過來的,方便下面代碼實現的時候做對比)

      協議的理解和實現主要就是要對協議報文理解。(注意:以下報文數據都是十六進制)

      數據【讀取-請求報文】:19 B2 00 00 00 06 02 03 00 04 00 01

      • 19 B2 是客戶端發的檢驗信息,隨意定義。
      • 00 00 代表是基于tcp/ip協議的modbus
      • 00 06 標識后面還有多長的字節
      • 02 表示站號地址
      • 03 為功能碼(讀保持寄存器)
      • 00 04 為寄存器地址
      • 00 01 為寄存器的長度(寄存器個數)

      數據【讀取-響應報文】(分兩次獲取)

      第一次獲取前八個字節(Map報文頭):19 B2 00 00 00 05 02 03 02 00 20

      • 19 B2 檢驗驗證信息(復制的客戶端發的,配件檢驗)
      • 00 00 代表是基于tcp/ip協議的modbus(復制的客戶端發的)
      • 00 05 為當前位置到最后的長度
      • 02 表示站號地址(復制的客戶端發的)
      • 03 為功能碼(復制的客戶端發的)

      第二次獲取的報文:02 00 20

      • 02 字節個數
      • 00 20 響應的數據

      數據【寫入-請求報文】:19 B2 00 00 00 09 02 10 00 04 00 01 02 00 20

      • 19 B2 是客戶端發的檢驗信息,隨意定義。
      • 00 00 代表是基于tcp/ip協議的modbus
      • 00 09 從本字節下一個到最后
      • 02 站號
      • 10 功能碼(轉十進制就是16)
      • 00 04 寄存器地址
      • 00 01 寄存器的長度(寄存器個數)
      • 02 寫字節的個數
      • 00 20 要寫入的值(轉十進制為32)

      數據【寫入-響應報文】:19 B2 00 00 00 06 02 10 00 04 00 01

      和請求報文的區別

      • 沒有了請求報文的數據值
      • 00 09 變成了00 06 因為報文長度變了
      • 其他的報文意義和請求報文一致

      實現

      //啟動服務
      public void Start()
      {
          //1 創建Socket對象
          var socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      
          //2 綁定ip和端口 
          IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 502);
          socketServer.Bind(ipEndPoint);
      
          //3、開啟偵聽(等待客戶機發出的連接),并設置最大客戶端連接數為10
          socketServer.Listen(10);
      
          Task.Run(() => { Accept(socketServer); });
      }
      
      //客戶端連接到服務端
      void Accept(Socket socket)
      {
          while (true)
          {
              //阻塞等待客戶端連接
              Socket newSocket = socket.Accept();
              Task.Run(() => { Receive(newSocket); });
          }
      }
      

      以上都和我們前面的一樣,這了不一樣的地方就是對請求報文的解析和響應報文的組裝發送

      //接收客戶端發送的消息
      void Receive(Socket newSocket)
      {
          while (newSocket.Connected)
          {
              byte[] requetData1 = new byte[8];
              //讀取客戶端發送報文 報文頭
              int readLeng = newSocket.Receive(requetData1, 0, requetData1.Length, SocketFlags.None);
              byte[] requetData2 = new byte[requetData1[5] - 2];
              //讀取客戶端發送報文 報文數據
              readLeng = newSocket.Receive(requetData2, 0, requetData2.Length, SocketFlags.None);
              var requetData = requetData1.Concat(requetData2).ToArray();
      
              byte[] responseData1 = new byte[8];
              //復制請求報文中的報文頭
              Buffer.BlockCopy(requetData, 0, responseData1, 0, responseData1.Length);
              //這里可以自己實現一個對象,用來存儲客戶端寫入的數據(也可以用redis等實現數據的持久化)
              DataPersist data = new DataPersist("");
      
              //根據協議,報文的第八個字節是功能碼(前面我們有說過 03:讀保持寄存器  16:寫多個寄存器)
              switch (requetData[7])
              {
                  //讀保持寄存器
                  case 3:
                      {
                          var value = data.Read(requetData[9]);
                          short.TryParse(value, out short resultValue);
                          var bytes = BitConverter.GetBytes(resultValue);
                          //當前位置到最后的長度
                          responseData1[5] = (byte)(3 + bytes.Length);
                          byte[] responseData2 = new byte[3] { (byte)bytes.Length, bytes[1], bytes[0] };
                          var responseData = responseData1.Concat(responseData2).ToArray();
                          newSocket.Send(responseData);
                      }
                      break;
                  //寫多個寄存器
                  case 16:
                      {
                          data.Write(requetData[9], requetData[requetData.Length - 1].ToString());
                          var responseData = new byte[12];
                          Buffer.BlockCopy(requetData, 0, responseData, 0, responseData.Length);
                          responseData[5] = 6;
                          newSocket.Send(responseData);
                      }
                      break;
              }
          }
      }
      

      這段要點就是根據請求報文獲得功能碼,然后對報文數據進行讀取或寫入動作。當然你完全可以對寫入的數據進行持久化存儲(如用redis),這樣在斷電或重啟后數據依然可以正常讀取。
      當然,以上只是個類偽代碼,為了減少代碼量和方便理解,很多情況和實際可能性沒有做對應的處理。

      IoTClient中ModBusTcp協議的使用

      安裝

      Nuget安裝 Install-Package IoTClient
      或圖形化安裝

      使用

      //1、實例化客戶端 - 輸入正確的IP和端口
      ModBusTcpClient client = new ModBusTcpClient("127.0.0.1", 502);
      
      //2、寫操作 - 參數依次是:地址 、值 、站號 、功能碼
      client.Write("4", (short)33, 2, 16);
      client.Write("4", (short)3344, 2, 16);
      
      //3、讀操作 - 參數依次是:地址 、站號 、功能碼
      var value = client.ReadInt16("4", 2, 3).Value;
      var value2 = client.ReadInt32("4", 2, 3).Value;
      
      //4、如果沒有主動Open,則會每次讀寫操作的時候自動打開自動和關閉連接,這樣會使讀寫效率大大減低。所以建議手動Open和Close。
      client.Open();
      
      //5、讀寫操作都會返回操作結果對象Result
      var result = client.ReadInt16("4", 2, 3);
      //5.1 讀取是否成功(true或false)
      var isSucceed = result.IsSucceed;
      //5.2 讀取失敗的異常信息
      var errMsg = result.Err;
      //5.3 讀取操作實際發送的請求報文
      var requst  = result.Requst;
      //5.4 讀取操作服務端響應的報文
      var response = result.Response;
      //5.5 讀取到的值
      var value3 = result.Value;
      

      結束

      posted @ 2019-11-13 08:45  農碼一生  閱讀(4863)  評論(12)    收藏  舉報
      .
      主站蜘蛛池模板: 日本一区二区三区专线| 国产欧美日韩精品丝袜高跟鞋| 国产精品一区中文字幕| 精品国产一区av天美传媒| 老鸭窝在线视频| 亚洲天堂一区二区三区四区| 成人免费精品网站在线观看影片| 久久亚洲国产精品久久| 久久亚洲日韩精品一区二区三区| 亚洲午夜成人精品电影在线观看| 精品久久久久久久中文字幕| 亚洲欧美日韩人成在线播放| 在线观看中文字幕国产码| 日本免费人成视频在线观看| 亚洲人成网站77777在线观看 | 伊人中文在线最新版天堂| 漂亮人妻被修理工侵犯| 国产亚洲精品AA片在线爽| 欧美熟妇xxxxx欧美老妇不卡| 台湾佬自拍偷区亚洲综合| 国产suv精品一区二区四| 国产自在自线午夜精品| 337p粉嫩大胆色噜噜噜| 制服丝袜美腿一区二区| 国产亚洲av手机在线观看| 亚洲午夜无码久久久久蜜臀AV| 交口县| 国产情侣激情在线对白| 天堂影院一区二区三区四区| 满洲里市| 欧美日本精品一本二本三区| 乱人伦中文视频在线| 国产草草影院ccyycom| 国产精品入口麻豆| 中国帅小伙gaysextubevideo| 国产成人亚洲日韩欧美| 亚洲最大的成人网站| 岛国av在线播放观看| 亚洲精品日本久久久中文字幕 | 亚洲av综合色区在线观看| 国产精品午夜精品福利|