閱讀367 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Java網絡教程:Protocol Design

如果設計一個客戶端到服務器的係統,那麼同時也需要設計客戶端和服務器之間的通信協議。當然,有時候協議已經為你決定好了,比如HTTP、XML_RPC(http response 的 body 使用xml)、或者SOAP(也是http response 的 body 使用xml)。設計客戶端到服務端協議的時候,一旦協議決定開啟一會兒,來看一些你必須考慮的地方:

1. 客戶端到服務端的往返通訊

2.區分請求結束和響應結束。

3.防火牆穿透

客戶端-服務端往返

當客戶端和服務端通信,執行操作時,他們在交換信息。比如,客戶端執行一個服務請求,服務端嚐試完成這個請求,發回響應告訴客戶端結果。這種客戶端和服務端的信息交換就叫做往返。示意圖如下:
20160325151854515

當一個計算機(客戶端或者服務端)在網絡中發送數據到另一個計算機時,從數據發送到另一端接收數據完會花費一定時間。這就是數據在網絡間的傳送的時間花費。這個時間叫做延遲。

協議中含有越多的往返,協議變得越慢,延遲特別高。HTTP協議隻包含一個單獨的響應來執行服務。換句話說就是一個單獨的往返。另一方麵,在一封郵件發送前,SMTP協議包含了幾個客戶端和服務端的往返。

在協議中有多個往返的原因是:有大量的數據從客戶端發送到服務端。這種情況下你有2個選擇:

1.在分開往返中發送頭信息;

2.將消息分成更小的數據塊。

如果服務端能完成頭信息的一些初始驗證 ,那麼分開發送頭信息是很明智的。如果頭信息是空白的,發送大量數據本身就是浪費資源。

在傳輸大量數據時,如果網絡連接失敗了,得從頭開始重新發送數據。數據分割發送時,隻需要在網絡連接失敗處重新發送數據塊。已經發送成功的數據塊不需要重新發送。

區分請求結束和響應結束

如果協議容許在同一個連接中發送多個請求,需要一個讓服務端知道當前請求何時結束、下一個請求何時開始。客戶端也需要知道一個響應何時結束了,下一個響應何時開始。

對於請求有2個方法區分結束:

1.在請求的開始處發送請求的字長

2.在請求數據的最後發送一個結束標記。

HTTP用第一個機製。在請求頭中 發送了“Content-Length”。請求頭會告訴服務端在頭文件後有多少字節是屬於請求的。

這個模型的優勢在於沒有請求結束標誌的開銷。為了避免數據看上去像請求結束標誌,也不需要對數據體進行編碼。

第一個方法的劣勢:在數據傳輸前,發送者必須知道多少字節數將被傳輸。如果數據時動態生成的,在發送前,首先你得緩存所有的數據,這樣才能計算出數據的字節數。

運用請求結束標誌時,不需要知道發送了多少字節數。隻需要知道請求結束標誌在數據的末尾。當然,必須確認已發送的數據中不包含會導致請求結束標誌錯誤的數據。可以這樣做:

可以說請求結束標誌是字節值255。當然數據可能包含值255。因此,對數據中包含值255的每一個字節添加一個額外的字節,還有值255。結束請求標誌被從字節值255到255之後的值為0。如下編碼:

255 in data –>255, 255

end-of-request –> 255, 0

這種255,0的序列永遠不會出現在數據中,因為你把所有的值255變成了255,255。同時,255,255,0也不會被錯認為255,0。255,255被理解成在一起的,0是單獨的。

防火牆穿透

比起HTTP協議,大多數防火牆會攔截所有的其他通信。因此把協議放在HTTP的上層是個好方法,像XML-RPC,SOAP和REST也可以這樣做。

協議置於HTTP的上層,在客戶端和服務端的HTTP請求和響應中可以來回發送數據。記住,HTTP請求和響應不止包含text或者HTML。也可以在裏麵發送二進製數據。

將請求放置在HTTP協議上,唯一有點奇怪的是:HTTP請求必須包含一個“主機”頭字段。如果你在HTTP協議上設計P2P協議,同樣的人最可能不會運行多個“主機”。在這種情況下需要頭字段是不必要的開銷(但是個小開銷)。

轉載自 並發編程網 - ifeve.com

最後更新:2017-05-19 17:02:17

  上一篇:go  沙龍報名啦:頂級架構師為您講述企業互聯網架構優化升級之路(阿裏雲授權中心沙龍計劃)
  下一篇:go  複製安全組小工具