我無法理解使用固定大小前綴長度標頭的消息框架是如何工作的。據說一個固定大小的字節數組將包含要發送的消息的長度。但是你將如何定義一個固定大小的字節數組,特別是在 Golang 中。說這是我的信息:Hello它的長度是 5。因此,如果我想通過 tcp 流發送它,為了確保我在另一端收到所有消息,我必須告訴它應該讀取多少字節。一個簡單的標題是length:message:5:Hello // [53 58 104 101 108 108 111]但是如果消息長度每次增長 10 倍,就會有更多的字節。所以標題大小是動態的。36:Hello, this is just a dumb question. // [51 54 58 72 101 108 108 111 44 32 116 104 105 115 32 105 115 32 106 117 115 116 32 97 32 100 117 109 98 32 113 117 101 115 116 105 111 110 46]所以這里36需要2個字節。我想到的一種方法是考慮協議的最大消息長度。假設 10KB = 10240 字節。然后將前導添加0到消息長度。這樣,我確定我將擁有一個固定的 5 字節標頭。這適用于所有情況嗎?如果是,如果我有超過 10KB 的消息,我應該將其拆分為 2 條消息嗎?如果不是,還有什么其他解決方案?我想在 Golang 中實現解決方案。更新 1:我讀過關于 Endians 的文章,盡管我無法理解他們做了什么會導致固定長度的字節。但是我在python中找到了一個示例,并嘗試以這種方式編寫它:客戶: const maxLengthBytes = 8 conn, err := net.Dial("tcp", "127.0.0.1:9999") if err != nil { fmt.Println(err) return } message := "Hello, this is just a dumb question" bs := make([]byte, maxLengthBytes) binary.LittleEndian.PutUint64(bs, uint64(len(text))) bytes := append(bs, []byte(text)...) conn.Write(bytes)服務器: listener, err := net.ListenTCP("tcp", &net.TCPAddr{Port: 9999}) if err != nil { fmt.Println(err) return } for { tcp, err := listener.AcceptTCP() if err != nil { fmt.Println(err) continue } go Reader(tcp) }func Reader(conn *net.TCPConn) { foundLength := false messageLength := 0 for { if !foundLength { var b = make([]byte, maxLengthBytes) read, err := conn.Read(b) if err != nil { fmt.Println(err) continue } if read != 8 { fmt.Println("invalid header") continue } } }}
1 回答

炎炎設計
TA貢獻1808條經驗 獲得超4個贊
請參考我在這篇文章中的回答 TCP client for Android: text is not received full
基本上,您必須定義數據如何存儲/格式化。例如:
我們將前綴長度存儲為
int32
(4 字節),小端。它和你的不一樣。使用您的解決方案,長度是 a
string
,很難確定長度。對于您的解決方案,您必須使用固定長度的字符串。例如:10 個字符,并添加前導零。
對于您的問題。
它不適用于只有前綴長度的所有情況。它有它的局限性,例如如果我們使用
int32
前綴長度,消息的長度必須小于 Integer32.max,對嗎?是的,我們必須拆分甚至合并(請參閱我在上面鏈接中的解釋)。
如果這是我們關心的問題,我們有很多方法來處理長度限制(實際上,幾乎應用程序協議都有最大請求大?。?。您可以多用一位來指示消息是否超過最大長度來解決它,對嗎?
- 1 回答
- 0 關注
- 205 瀏覽
添加回答
舉報
0/150
提交
取消