長連線TCP傳輸層如何定義合理的幀結構?

時間 2021-06-02 11:57:13

1樓:Bruce Wayne

len | payload 足以作為你的應用層協議。payload裡面根據業務實際需求再分成實際的域,或者key-val,或者字串。幾個主要問題和解決方法:

1. 大包。比如你的len是Short,而payload有可能大於這個長度。方法:

應用層拆包,第乙個包len設為0xFFFF,如果接下去還是不夠,繼續0xFFFF,直到最後乙個是乙個小於0xFFFF的包。這是MySQL的協議。

2.必須要確保先讀完整的包頭,包括裡面的len欄位,然後再迴圈讀出所有的剩餘payload。如果讀不到就懵逼了。方法:

使用lenth-encoded長度表示。玩法自己可以bing,作用是len可變長,表徵payload長度。只要能讀乙個Byte,就能順藤摸瓜讀乙個完整的包。

由於Byte是基本單位,不用擔心讀到不完整len放棄。並且也可以解決大包問題。

2樓:狼大人

幀長度確定之後,幀頭 / 尾不需要任何 delimiter。

如果用二進位制傳輸幀長度資訊,則幀長度和 payload 之間也不需要 delimiter。IP / TCP 頭都是這樣,在固定位置用固定位元組序的二進位制標記 payload 長度。

長度資訊如果不是二進位制,參考下面的 chunked transfer-encoding 例子。

需要在內容中轉譯的 delimiter 的作用是在 length 未知的情況下劃分訊息邊界。

以 HTTP 舉例,內容長度可以提前知道的情況,比如有 Content-Length 的 response entity,是可以沒有 delimiter 的,因為 Content-Length 已經確定了訊息的邊界。

乙個稍微複雜的例子是 HTTP Chunked Encoding Chunked transfer encoding

Chunked-Body = *chunklast-chunktrailerCRLF

chunkchunk-size [ chunk-extension ] CRLF chunk-data CRLF

chunk-size = 1*HEX

last-chunk = 1*("0") [ chunk-extension ] CRLF

在每個 chunk 裡,chunk-data 之前的 CRLF 是乙個未知長度的變長訊息(chunk-size + chunk-extension)的邊界;而這個訊息裡是不可能出現 CRLF 的,所以不存在轉義的問題。

chunk-data 的長度是已知的,所以裡面包含 CRLF 也是不需要轉義的。

按照我的理解,chunk-data 之後的 CRLF 實際上唯一的作用在於「如果這裡不是 CRLF 那麼一定出錯了」。這是乙個簡單的校驗,換成 @靳小都 所說的在這裡放 CRC 也是一樣的。

另外可以參考的:XDR: https://

en.wikipedia.org/wiki/E

xternal_Data_Representation

以及真的沒法直接用 protobuf 麼……

TCP短連線和長連線的區別

公尺夏 畢業酒喝多了,班長站在桌上高喊 20年後,我們要做到秒薪一塊錢!某同學2015年成立某單車,占股14.63 目前估值300億,個人身價43億。已完成任務。用時13年。 Tball 剛畢業的時候,其實不是很懂自己要做什麼,想考乙個教師編制,第一年沒考上,後來也在為這個做準備,心裡卻明白自己還是...

WebSocket 相比普通的 TCP 長連線有什麼優勢?

WebSocket 是應用層協議,tcp 是傳輸層協議。websocket 本身是基於 tcp 實現的。tcp 本身無所謂長短連線,理想狀態下只要不 close,tcp 連線就一直存在 注意是理想 所謂的長連線本身是一條虛擬鏈路。所以這個問題沒法回答。 A yon 首先需要指出這個 WebSocke...

如何解決長城寬頻主動斷開tcp長連線的問題?

鶴83 你用長寬線路和你的伺服器傳輸資料,不超過5M頻寬說明該阿里雲IP沒有接入長城寬頻線路,換多幾個阿里雲IP,再不行可以換區域試試。 只能打長寬客服轉機房網管做白名單解決。TCP IP協議下,出口路由的埠只有65536個,長寬乙個出口路由下內網使用者太多,為了不讓高峰時長鏈結佔滿了出口路由埠,埠...