這裡說的TCP協定偵錯定義是在開發長連線TCP協定應用時,為了驗證程式碼流程或查詢bug,需要與對端互動資料過來,當需要時可以暫停傳送;單條傳送;跳過傳送;正常傳送;傳送時修改資料等。
TcpEngine提供的解決方案是:我們前端應用和後端應用網路通訊時,先經過TcpEngine轉發,在轉發過程中,可以對網路資料暫停轉發(暫停);單條轉發(單步);正常轉發(執行);轉發前編輯資料或轉發手工製造的資料(手工傳送)等操作,解決我們在開發TCP協定應用時碰到的下列幾種情況。
一、前端小組和後端小組協商後協定格式後,就分別開發新功能,在開發過程中需要對端小組傳送網路資料過來觸發程式碼執行,以驗證程式碼流程是否正確。但是對端小組也正在開發,功能不完善也不能給你發資料,此時只能盲寫程式碼。另一種情況是我們已經寫完程式碼,需要對端小組傳送資料過來,觸發程式碼以驗證流程是否正確,但對端功能不完善也不能給你發資料,只能乾等待?此時可以使用TcpEngine模擬對端傳送資料給自己,觸發程式碼執行。
二、新功能已經整合提交到測試階段,在測試過程中發生bug,此時需要對端傳送資料過來定位錯誤,但由於對端也在解決bug沒時間或不能重現錯誤資料,此時無法通過網路資料觸程式碼流程來查詢bug。此時也可以使用TcpEngine摸擬對端給資料給自己。
三、應用已經交付給使用者端,客戶使用過程中發生網路資料錯誤,需要儲存現場資料,解析以重現錯誤現場。此時我們可以使用TcpEngine開啟代理伺服器,讓前端應用和後端應用的資料通訊經過TcpEngine轉發,TcpEngine轉發資料同時解析和儲存現場資料,再次使用TcpEngine開啟解析,以重現網路的網路資料。
新版本放棄了WFP核心獲取網路資料方式,改用代理伺服器獲取網路,帶來易用性很大的提升,新增了TCP協定偵錯執行模式,新增的功能有:暫停;單步;跳過;執行等新功能。
TcpEngine使用代理伺服器方式擷取網路資料,前端需要通過代理使用者端把資料傳送給TcpEngine的代理伺服器模組,TcpEngine收到資料進行解析並顯示,然後把解析後的資料再次封裝轉發給後端,資料流程圖如下圖所示。
下面我們以一個最簡單的應用來演示TcpEngine怎麼使用,這個應用非常簡單,前端傳送一條資料給後端,後端就響應一條資料給前端。前端和後端都是用java1.8開發,後端已經部署到demo.tcpengine.cn 伺服器,執行前端需要已設定java環境,程式碼已放到https://gitee.com/www.csdn.net/tcp-engine-test。
一、我們以ProxyCap來做為代理使用者端,安裝ProxyCap成功後會通知區域顯示ProxyCap圖示,如下圖所示。
二、右鍵ProxyCap圖示彈出設定選單,點選Configuration按鈕,如下圖所示。
四、點選右邊導航樹的Proxies,再點選New Proxy Server小圖示,新建一條指向代理伺服器的設定資訊,如下圖所示。
五、點選導航樹的Rules,再點選Quick Add Rule小圖示,把我們的前端應用exe檔案加入到ProxyCap,如下圖所示。
查詢前端應用exe檔案的小技巧
一、開啟工作管理員。
二、再啟動我們的前端應用,這時前端應用就新增到工作管理員應用列表,如下圖所示。
三、滑鼠右鍵我們的應用,點選「開啟檔案所在的位置(O)」,就可定位到我們應用exe檔案的位置,如下圖所示。
如下圖所示,到此我們成功的把前端應用加入到了ProxyCap代理使用者端,當我們再啟動前端應用時,前端應用的所有TCP網路資料都由ProxyCap轉發給代理伺服器,再由代理伺服器轉發資料給後端應用。
啟動TcpEngine,初始的主介面如下圖所示。
代理伺服器啟動成功如下圖所示,點選「退出」僅隱藏視窗,對代理伺服器執行狀態沒有影響,只有TcpEngine退出後,代理伺服器才停止執行。
如果我們啟動失敗,彈出下圖所示異常對話方塊,那麼是因為系統沒有安裝Visual C++ 14 Runtime Libraries (C++執行支援庫),到微軟體官網或這裡https://tcp-engine.oss-cn-shenzhen.aliyuncs.com/vc_redist.x64.exe下載並安裝就可以解決。
如下圖所示,點選主視窗的新建按鈕。
新建一個空的解析視窗,如下圖所示。
點選「開始」,彈出網路設定對話方塊,填入後端應用的網路地址和埠,點選「接收不解析」按鈕,把網路設定加入代理伺服器的資料擷取列表,如下圖所示。
解析主介面開始監聽網路資料如下圖所示。
啟動TcpEngineClient,下載地址:http://www.tcpengine.cn/tcp_engine/down_list.html,下載TcpEngine1.3.0.zip到本地,如下圖所示。
解壓後在TcpEngine1.3.0\demo\TcpEngineClient目標下有兩個檔案startupClient.bat;TcpEngineClient.jar,雙擊startupClient.bat(注意,執行前本機必須設定好java執行環境,本範例是在java1.8下開發的),範例主介面如下圖所示。
一、點選「連線」;二、點選「傳送1000」,傳送一條TCP協定到後端並從後端接收一條TCP,如下圖所示。
再檢視TcpEngine介面,顯示TcpEngine已擷取到TcpEngine協定資料,如下圖所示。
本範例演示TCP協定格式如下圖所示,訊息體長度就第二個int型訊息體長度決定。
對應的解析規則如下所示。
int32 id;
int32 len;
if(0 < len)
{
byte[len] body; // 訊息體
}
來自前端id=1000訊息的訊息體如下圖所示。
對應的訊息體的解析規則如下所示。
if(1000 == id) {
int32 loginId = split(body);
string[len - 4] = split(body);
}
完整的解析規則如下所示。
set endian = big;
set encoding = utf-8;
int32 id;
int32 len;
if(0 < len)
{
byte[len] body; // 訊息體
if(1000 == id)
{
int32 loginId = split(body);
string[len - 4] = split(body);
}
}
一、點選「停止」;二、輸入解析規則到前端解析規則視窗;三、點選重新整理,四、點選「重新整理並解析」,把TCP協定解析成正常資料,如下圖所示。
在長連線TCP協定開發中,每個應用都會根據自身的業務特點,定義不同的TCP協定格式,TCP協定具有千變萬化的特點。面對多變的TCP協定,TcpEngine借鑑程式設計的部分思路,定義了資料型別;if分支;for迴圈;算術表示式來組成解析規則。解析規則的執行過程是從上往下順序執行,當執行到結尾再回圈從頭開始新一輪執行,比如下圖所示的解析規則。
這個解析規則的流程圖如下所示。
網路資料環境指的是大小端和字串編碼環境,在實際應用是,有基本數值資料型別,如int32;float32等,這類資料型別因為硬體平臺不同而有大小端的區別,設定大小端的指令是set endian = big; 。字串資料型別會有編碼區別,設定網路字串編碼指令是set encoding = utf-8;。資料環境指令寫在解析規則的開頭,如下圖所示。
char 字元型,一個位元組,顯示ASCII 字元。
byte 位元組型,一個位元組,以十六進位制顯示。
int8 有符號整型,一個位元組,以十進位制顯示。
uint8 無符號整型,一個位元組,以十進位制顯示。
int16 有符號整型,兩個位元組,以十進位制顯示。
uint16 無符號整型,兩個位元組,以十進位制顯示。
int32 有符號整型,四個位元組,以十進位制顯示。
uint32 無符號整型,四個位元組,以十進位制顯示。
int64 有符號整型,八個位元組,以十進位制顯示。
uint64 無符號整型,八個位元組,以十進位制顯示。
float32 浮點型,四個位元組,以十進位制顯示。
float64 浮點型,八個位元組,以十進位制顯示。
string 字串型,可變長度,如果指定了長度,則按指定長度劃分位元組數,如果不指定長度,一直劃分到遇到零為止,如果沒有零,一直劃分到本行結束。
基本資料型別陣列概念與程式設計中的陣列概念類似,是把連續的網路數位流劃分到連續的記憶體中,定義格式是 基本資料型別[陣列大小表示式] 陣列的幾種定義方式如下。
使用常數定義陣列長度,如int16[3],定義了三個兩位元組整型陣列,共佔用6個位元組長度。
使用變數定義陣列長度,如byte[len],由變數動態指定陣列長度。
使用算術表示式定義陣列長度,如int32[1+2*3]; string[len-4]; 等。
陣列的長度計算方式是資料型別長度 * 陣列元素數,比如int32[3]佔用12個位元組,float64[4]佔用32個位元組。字串的資料型別長度是1個位元組,string[32]佔用32個位元組,如下圖所示。
跟程式中的算術表示式一樣,算術表式達的計算結果是數值,可用於陣列長度計算,變數賦值。變數值來源有兩種,一種是來源於網路資料劃分,另一種是來源於算術表示式,值來源不同的變數執行表現有下列不同。
一、來源於網路的變數在介面上有顯示,而來源於表示式變數不會被顯示。
二、來源於網路的變數值不能被改變,而來源於表示式變數可以被改變,如執行++運算。
支援if;for,不支援while,跟程式的行為一樣,有一點區別是if的格式如下。
if()
{
執行分支段......
}
elseif() // 注意這裡else 和 if 之間沒有空間
{
執行分支段......
}
else
{
執行分支段......
}
簡單的範例如下圖所示。
TcpEngine不支援自定義函數,本版本僅定義了兩個內建函數,分別是split和call。split是對陣列再一次劃分到新變數,用法與效果前面已經說明和展示了,這裡不再介紹。call是支援偵錯模式執行,這個內建函數在偵錯解析再詳細說明。
這個版本新增的最重要功能,也是最實用功能,由暫停;忽略;穿透暫停;執行;手工傳送等子功能組成。觸發調式模式有兩種方式,一、在執行中,手工點選工具列的「暫停」按鈕;二、在解決規則上加入call(pause);。
偵錯TCP協定的定義是:我們前端應用和後端應用網路通訊時,先經過TcpEngine轉發,在轉發過程中,可以網路資料暫停轉發(暫停);單條轉發(單步);正常轉發(執行);轉發前修改資料或轉發手工製造的資料(手工傳送)等操作,本節用開源的IM軟體flamingo演示,flamingo的原始碼託管地址 https://gitee.com/balloonwj/flamingo。
一、flamingo後端已放到demo.tcpengine.cn,伺服器埠是20000;20001;20002,flamingo前端網路設定如下圖所示。
二、參考前面的教學把flamingo加入到ProxyCap,如下圖所示。
三、編寫解析規則,flamingo的TCP協定格式如下圖所示
對應的解析規則如下圖所示。
新建空的解析視窗,編寫解析規則,點選工具列的「開始」按鈕,因為flamingo對網路資料進行了加密,我們需要設定加解庫(加解庫會在「對加解密的支援」章節講解),如下圖所示。
啟動監聽網路資料成功如下圖所示。
啟動flamingo,輸入使用者名稱:13888886666 密碼:123456 並點選登陸(測試環境,資料可能會被清除),如下圖所示。
flamingo登陸成功,TcpEngine解析TCP協定結果如下圖所示。
我把flamingo的指令分業務指令和支援指令,業務指令由使用者觸發,比如登陸;查詢;聊天等指令;支援指令由應用自己傳送,比如心跳指令。
觸發偵錯模式有兩種方式,一、點選工具列的「暫停」按鈕;二、使用call內建函數支援,在解析規則中加入call(pause)。
在實際應用中,我們不想顯示一些指令的解析結果,比如心跳指令有很多但對我們查詢問題沒有幫助,這類指令的解析結果我們可以隱藏並且不影響指令轉發。那麼我們可以在解析規則中加入call(ignore)觸發這個功能,比如我們對心跳包的結果隱藏如下圖所示。
有時候我們希望網路資料解析到某條指令就暫停轉發,阻塞住後面到達的資料,用於仔細分析網路現場資料或者修改資料後再傳送。觸發這個功能有兩種方式,一、點選工具列暫停按鈕;二、在解析規則中加入call(pause),如下圖所示,當解析到指令id = 1004 時,TcpEngine暫停轉發資料。
當我們觸發「暫停」功能後,有一個問題需要解決,就是心跳指令也阻塞住了,如果我們的應用發現收不到心跳指令,可能會認識網路已經斷開了,從而主動斷開網路。那麼我們需要在阻塞網路資料的時候,某些指令還能繼續轉發,在解析規則中加入call(tunnel)可以實現本功能,如下圖所示,當阻塞在1004指令時,心跳指令還能繼續轉發。
在工具的按鈕有,暫停|執行;單步;跳過,功能說明如下。
暫停|執行:當解析執行緒阻塞轉發時,顯示「執行」,點選解析執行緒繼續解析並轉發;當解析執行緒正常解析並轉發資料時,顯示暫停,點選會阻塞解析和轉發,暫停的行為跟call(pause)的為行一致。
單步:當解析執行緒阻塞時,本按鈕可點選,點選會把當前阻塞的資料轉發到網路,並把下一條網路資料取出解析顯示並繼續阻塞。
跳過:當解析執行緒阻塞時,本按鈕可點選,點選會把當前阻塞的資料丟棄,並把下一條網路資料取出解析顯示並繼續阻塞。
在開發TCP長連線應用時,常常會發生「簡介」章節列舉的這幾種情況,在對端無法向我們傳送資料時,可以使用TcpEngine向我們傳送模擬資料,實現這個功能就是手工傳送,操作流程如下。
在轉發模式下,讓解析執行緒執行到指定指令就暫停下來,本範例我們就讓解析執行緒執行到指令1004就暫停解析。
滑鼠雙擊你要傳送的資料,彈出二次解析視窗,如下圖所示。
在二次解析視窗編輯網路資料,如下圖所示。
滑鼠右鍵選單,點選「傳送」,如下圖所示。
多數情況下,在網路上流通的資料都是經過加密的,每個應用的加解密演演算法都是不同並保密的。面對這種情況TcpEngine提供的解決方案是由您根據自身的加解密演演算法,按照我們的規則封閉成DLL,並在開始解析網路資料前設定到網路解析視窗,設定加解庫如下圖所示。
解碼庫地址:加解密庫DLL在原生的地址,如果資料沒有加密,則設定為空。
解碼初始化引數:當解析執行緒載入加密庫時,在加密或解密資料前,會對這裡輸入引數進行驗證,驗證通過再加解密資料,設計這個引數的目的是防止您的DLL流出,讓別有用心的人利用DLL解密您的資料並攻擊你的應用,如果設定了引數,別人不知道引數也不能使用您的DLL,相當於密碼的功能。
選填/必填:選填,初始化引數可填可不填,如果已填,就對初始化引數驗證;必填,初始化引數必須填寫並驗證。
儲存:勾選這個,寫把初始化引數儲存tcpd檔案,再次開啟tcpd檔案引數裝自動填充。
加解密庫有兩類介面,一類是由TcpEngine呼叫,DLL實現的介面;另一類是由TcpEngine實現,DLL呼叫的介面,這類介面稱為回撥函數。
由TcpEngine呼叫DLL實現的介面如下圖所示。
由TcpEngine實現DLL呼叫的介面如下圖所示。
DLL庫開發的請參考基於flamingo的DLL原始碼,代理下載地址:https://gitee.com/www.csdn.net/TcpEngineDecode.git