JAVA版基於netty的物聯網閘道器
阿新 • • 發佈:2018-12-16
專案地址:https://gitee.com/willbeahero/IOTGate 通過netty實現自定義協議物聯網閘道器(附有報文格式) window膝上型電腦本地測試:單閘道器、單前置節點,每秒處理上行併發心跳4000+(併發下行未統計),20W線上終端記憶體佔用量1G 終端心跳檢測,終端超過300秒無應答,則閘道器主動關閉通道,並清理快取 目前設定的閘道器與前置channel通訊的channel高低水位為,低水位32M,高水位64M。 new WriteBufferWaterMark(32 * 1024 * 1024, 64 * 1024 * 1024) 設定水位線的作用是:防止伺服器處理能力極其低下但連線正常時,造成channel中快取大量資料影響閘道器效能 *************************************************************************************************************************** 1. 入口類: Server4Terminal.java *************************************************************************************************************************** 2. 專案結構及說明: --------------------------------輔助包---------------------------- @ base包(基本類) |-cache包 | | | ClientChannelCache.java 用於儲存大量終端與閘道器連線之後 建立的channel例項,在閘道器接收到前置 | 傳送過來的的下行報文之後,需要通過終端ip獲取channel併發送資料) |-chachequeue包 | | | CacheQueue.java類封裝了其他一些ConcurrentHashMap,一些資料流轉用的對列等 | |-constant包 | | | ConstantValue.java 常量類 | |-domain包 | |ChannelData.java 封裝了ipAddress屬性(每個終端建立連線時,獲取終端的ip地址)組合了SocketData物件, |SocketData.java 封裝了終端傳送到閘道器的報文資訊(我稱之為“真實報文”) |GateHeader.java 封裝了閘道器報頭拼裝的一些工具方法 @ threadWorkers包(自定義執行緒) | TServer2MClient.java 實現了Runnable介面,用於從CacheQueue.up2MasterQueue佇列中獲取資料併發送到前置(具體實現 看程式碼) @ util包(工具包) | |CommonUtil.java 通用工具類 *StringUtils.java 用於 位元組陣列 與 String字串之間的相關轉化等 ---------------------------------通訊包------------------------------------ @ server包(服務端) | | | Server4Terminal.java “入口類” 閘道器獲取終端連線請求的服務端 | |-handler包 | SocketInHandler.java “入站控制器” 所有閘道器與終端連線建立的channel的pipeline中繫結該handler @ client包(客戶端) | | | Client2Master.java 閘道器請求連線到前置的客戶端 | |-handler包 | Client2MasterInHandler.java “入站控制器” 繫結到Client2Master @ codec包(編解碼器) | |Gate2ClientDecoder.java 自定義閘道器到終端通訊 解碼器 作用:byte[] ---> domain |Gate2ClientEncoder.java 自定義閘道器到終端通訊 編碼器 作用:domain ---> byte[] |Gate2MasterDecoder.java 自定義閘道器到前置通訊 解碼器 作用:1.去閘道器頭(A8開頭長度28個位元組)2.byte[] ---> domain Gate2MasterEncoder.java 自定義閘道器到前置通訊 編碼器 作用:1.加閘道器頭(A8開頭長度28個位元組)2.domain ---> byte[] --------------------------------輔助測試包--------------------------------- @ test包(輔助測試) | | | | | CountHelper.java 定義了模擬終端、模擬前置需要一些基本的併發計數功能的變數 | |-moniMaster包 | | | |moniMaster.java “入口類” 模擬前置服務端 | |moniMasterHandler.java 模擬前置服務端handler | moniMasterDecoder.java 模擬前置的解碼器***** | |-moniTerminal包 |moniTerminal.java “入口類” 模擬終端客戶端--併發模擬--moniMasterHandler類中判斷時間依據本類的併發量 moniTerminalHandler.java 模擬終端handler *************************************************************************************************************************** 3. 自定義閘道器報頭的結構與注意事項 *閘道器報頭,是閘道器與前置通訊時,作為閘道器登入和傳輸真實報文時攜帶閘道器自身和終端響應引數的報文,報文 *結構是自己定義,前置按照定義好的報文格式獲取資料並做相應處理。 閘道器報頭結構: A8 --- 1byte 報文頭 len --- 2byte 長度域:真實報文長度,包含“68”,“16” type --- 1byte 報頭型別 protocolType --- 1byte 協議型別 gateNum --- 1byte 閘道器編號 00*12 --- 12byte 00佔一個位元組,一共12個位元組,固定結構 clientIP --- 4byte 終端的IP地址,ip地址的每個段位佔一個位元組(不含符號和埠號) port --- 2byte 終端對應的埠號 count --- 4byte 終端與閘道器建立連線時對應的連線序號(1-10000迴圈) * 組閘道器報頭---閘道器向前置傳送閘道器登入報文時與閘道器向前置傳送真實報文時 報頭區別: * 1.登入時長度為0;有真實報文時,長度域為整個真實報文長度值 * 2.登入時type = 03;protocolType=15;count=1都為固定值;傳送真實報文時,type=01,protocolType=00;count=終端與閘道器的連線序號 ---前置發現報頭長度為0 且type = 03; protocolType=15;就不會執行解析資料的方法,否則會繼續解析真實報文 *************************************************************************************************************************** 4.真實報文結構與注意事項 *“真實報文”即終端與閘道器通訊使用的報文,規約不同可能結構會有所差異 真實報文結構: 68 --- 1byte 報頭 len --- 2byte 長度域 "傳輸幀中除起始字元和結束字元之外的幀位元組數" ... --- len byte 報文內容 16 --- 1byte 報尾 閘道器需要在解碼器中做真實報文的“真實性”、“完整性”驗證,只有驗證通過的報文才會被閘道器接收