t-io網路程式設計基礎知識介紹

manong發表於2021-10-08

一、 應用層和傳輸層

http協議為例,我們在訪問一個網站時,瀏覽器會透過TCP協議傳送如下字串到伺服器的應用層

GET /test/abtest HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: PHPSESSID=970260278652571648

程式除錯截圖 (tio的HttpRequest.toString())

這些字串就是應用層資料,應用層資料是按照一定格式來組織的,這個格式就是應用層協議,譬如 http協議。

傳輸層在往應用層傳遞資料時,並不保證每次傳遞的資料是一個完整的應用層資料包(以 http協議為例,就是並不保證應用層收到的資料剛好可以組成一個http包),這就是我們經常提到的半包和粘包。傳輸層只負責傳遞byte[]資料,應用層需要自己對byte[]資料進行解碼,以http協議為例,就是把byte[]解碼成http協議格式的字串。

具體請參考:

二、 ByteBuffer

引言

ByteBuffer是nio/aio程式設計所必須掌握的一個資料結構,也是掌握tio所必須要學會的基礎知識。

設想你不懂Map,不懂List,不懂Set,那麼你在程式設計領域將會一事無成,同樣的道理,如果你不懂ByteBuffer,你無法在nio/aio程式設計領域立足

初識ByteBuffer

我們可以把bytebuffer理解成如下幾個屬性組成的一個資料結構

byte[] bytes: 用來儲存資料

int capacity: 用來表示bytes的容量,那麼可以想像capacity就等於bytes.size(),此值在初始化bytes後,是不可變的。

int limit: 用來表示bytes實際裝了多少資料,可以容易想像得到limit <= capacity,此值是可靈活變動的

int position: 用來表示在哪個位置開始往bytes寫資料或是讀資料,此值是可靈活變動的

一圖感知一下ByteBuffer


具體請參考:

建立 ByteBuffer

ByteBuffer.allocate(int cap)即可建立一個指定容器大小的ByteBuffer,見圖


往ByteBuffer中寫入資料

呼叫 ByteBuffer.put(byte b)即可ByteBuffer中寫入一個位元組,見圖


從ByteBuffer讀取資料

對於剛剛寫好的 bytebuffer,我們要讀取它的內容,需要先設定一下position和limit,否則讀的位置就不對


接下來呼叫 ByteBuffer.get()即可讀取一個位元組,在讀取資料的同時,ByteBuffer的position也會跟關位移,見圖

三、 半包和粘包:正確斷句才能溝通

半包

顧名思義,就是收到了半個包,這個時候不足以組成一個應用層的包。就像你要對你喜歡的人說 “我喜歡你”,但是因為喝水嚥著了,第一次只說了“我”字,第二次說了個“喜”字,第三個次了個“歡你”,那麼就發生了半包問題,對方只有等待你說完這 4 個字後才知道你是想說“我喜歡你”!

http 協議為例,展示半包場景

粘包

粘包與半包相反,就是把多個想說的話,一口氣說完了,對方反應不過來,得把你的話拆開一條一條地理解

 

http 協議為例,展示粘包場景

說明: http 協議是一來一回的,所以正常場景是不會有粘包的,但 pipeline 模式下是允許一方連續發多個請求的,所以會有粘包產生

 

為何坑人無數

初涉網路程式設計的同學,往往認為每次收到的資料剛好是一個完整的資料包

於是當網路不好,或是訊息包過大時,半包的情況就發生了,而程式並沒有考慮到半包的情況,結果就是解碼失敗,導致訊息丟失

當通訊的對方把多條業務資料包放在一個 TCP 包中發過來時,粘包就產生了,而程式沒有考慮到一次 TCP 收包會收到多個業務包,從而解析到第一個業務包後把後面的業務包丟棄了

百度一下半包粘包,一定會搜到很多記錄,這也證明這倆貨確實坑人無數,所以看完本節內容,你還會繼續犯半包粘包的錯嗎?

具體請參考:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70006579/viewspace-2794872/,如需轉載,請註明出處,否則將追究法律責任。

相關文章