去年和今年分別參與了兩個公司的專案,這兩個專案都涉及到了通訊方面的程式設計,或者是以太網路通訊,或者是串列埠通訊。凡是通訊就必須要有通訊協議,個人認為協議的設計是個非常嚴肅的工作,需要理解業務需求和掌握基本的協議設計知識。但是從這兩個專案來看,其協議的設計可以說是糟糕到了極點。下面就其糟糕的設計之處予以批判。
與udp不同,tcp通訊屬於流式通訊,沒有訊息邊界,所以需要應用層自行對報文進行界定分離。實際專案1中,包頭為}兩個位元組,例如}。其格式為:
開始邊界+訊息1+結束邊界+開始邊界+訊息2+結束邊界+開始邊界+訊息3+結束邊界+....
由於tcp是安全的傳輸層協議,除非特別需要,應用層無需再做校驗。訊息邊界只需要乙個標識即可,基本格式為:
訊息1+邊界+訊息2+邊界+訊息3+邊界+...
無論從節約網路頻寬,還是從簡化報文解析**,第一種設計都是非常的愚蠢!
無獨有偶,專案2中基於串列埠的通訊應用層協議也採用了這種設計格式。
當問其設計人員為何如此設計時,說一直就是這麼設計的,自己也不知道這麼設計的原因,還美滋滋地說一直沒有什麼問題,真想揍他一拳。
專案2中,根本無協議的描述文字,只有乙個包含結構體定義的標頭檔案供協議的使用者參考。
通訊就會涉及到多個機器,所以通訊協議必須要能跨平台。而我們知道
struct a
;
在不同編譯器,不同平台,不同編譯選項下會有不同的二進位制布局。況且協議使用者也可能看不懂c系語言**。更搞笑的是,標頭檔案中竟然沒有強制結構體單位元組對齊。
問到協議的設計者設計思路時,說我們公司一直這樣啊,一直沒問題啊。之所以沒有問題,是因為使用這個協議的所有機器都是同一cpu型號,同一開發環境,同一作業系統。
浮點數的二進位制格式並不是只有一種,不同平台採用不同的方式存放。這要比大端小端的整數差別更加嚴重。所以跨平台傳送二進位制浮點數是非常不安全的。而在專案2中,訊息中大量使用了二進位制浮點數。
要傳送浮點數,通常有兩種解決方式:
專案二的訊息結構體類似如下:
struct a
;
大量的備用字段充斥在結構體中。少量的備用字段可以理解,如此大量的後備力量,真是深遠謀慮啊。真不知道協議使用者在看到spare時會不會吐。如果真的需要這麼多備用字段,完全可以重新定義乙個訊息結構了。
握手和校驗是保證安全完整通訊的基本手段,但是其實現卻非常不簡單,看看tcp的實現**就知道了,需要考慮各種異常情況。專案二中串列埠裝置和主機之間照貓畫虎地定義了乙個握手協議。開機後 裝置向主機一直傳送aa,主機收到aa後向裝置傳送aa,裝置收到aa後向主機傳送55,主機收到55後向裝置傳送55。這個簡單的握手存在很多問題,隨便說幾個:
如果主機傳送aa後程式退出,那麼串列埠裝置永遠也等不到來自主機的55。
如果主機中途關掉,在執行時可能收到來自串列埠裝置的aa,而此時的aa其實只是訊息報文的乙個位元組,而不是握手訊號。
只要仔細想想,還有很多類似的情況需要處理。而且實際使用過程中,確實發生了上面的情況,致使必須重啟串列埠裝置或主機。
還是專案2中,基於udp的應用層協議自行設計了校驗。其實這也無可厚非,比如著名的tftp就是這樣的協議。只是設計者考慮不周,各種問題頻出,最終的結果是這些校驗字段根本就沒有實際使用,白白浪費了網路頻寬。需要說明的是,這個協議的設計者還是國內很大的一家公司,當然是國企,***。
糟糕的應用層通訊協議設計
去年和今年分別參與了兩個公司的專案,這兩個專案都涉及到了通訊方面的程式設計,或者是以太網路通訊,或者是串列埠通訊。凡是通訊就必須要有通訊協議,個人認為協議的設計是個非常嚴肅的工作,需要理解業務需求和掌握基本的協議設計知識。但是從這兩個專案來看,其協議的設計可以說是 糟糕到了極點。下面就其糟糕的設計之...
應用層通訊協議的問題
做了不少物聯網通訊上的模組,也看過了各種各樣的協議解析,也學習了不少開源軟體的網路互動方式,不談那些http和其他一些封裝好的處理方法,總認為tcp丟包或者包錯了,那就會導致解析模組很容易卡住,比如長度位錯了,你還要一直找協議頭,始終找不到,群裡大佬都說tcp丟包和錯包不用考慮,那是硬體問題或系統問...
STM32開發 UART應用層通訊協議分析
拿到乙份uart的通訊協議,上手來操作之前先做一下分析。先看一下它的幀格式說明 1 幀頭標誌head 不論是命令幀還是響應幀,幀頭標誌都是0x92。2 協議版本 協議版本號 4bit 目前值為1 加密方式 4bit 0表示採取 資料不加密 校驗和 方式。所以,當前此欄位完整值為0x10 3 控制欄位...