Я не могу понять, как работает формирование сообщения с использованием заголовка длины префикса фиксированного размера.
Говорят, что массив байтов фиксированного размера будет содержать длину отправляемого сообщения. Но как бы вы определяли массив байтов фиксированного размера, в частности, в Golang.
Скажем, это мое сообщение:
Hello
Его длина равна 5.
Итак если я хочу отправить это через поток TCP, чтобы убедиться, что я получаю все сообщение на другом конце, мне нужно будет сказать ему, сколько байтов он должен прочитать.
Простой заголовок будет length:message
:
5:Hello // [53 58 104 101 108 108 111]
Но если длина сообщения увеличивается в 10 раз каждый раз, байтов будет больше. Таким образом, размер заголовка составляет c динамически.
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 байта.
Один из подходов, о котором я пришел, - это рассмотреть максимальную длину сообщения для протокол. Скажем, 10 КБ = 10240 байт. Затем добавьте к длине сообщения начальные 0
. Таким образом, я уверен, что у меня будет фиксированный 5-байтовый заголовок.
Будет ли это работать для всех случаев?
Если да, что, если у меня есть сообщение размером более 10 КБ , должен ли я разделить его на 2 сообщения?
Если нет, то каковы другие решения?
Я хочу реализовать решения в Golang.
ОБНОВЛЕНИЕ 1:
Я читал о порядке байтов, хотя не мог понять, что они делают, что вызывает байты фиксированной длины. Но я нашел пример в python и попытался записать его в go следующим образом:
Клиент:
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
}
foundLength = true
messageLength = int(binary.LittleEndian.Uint64(b))
} else {
var message = make([]byte, messageLength)
read, err := conn.Read(message)
if err != nil {
fmt.Println(err)
continue
}
if read != messageLength {
fmt.Println("invalid data")
continue
}
fmt.Println("Received:", string(message))
foundLength = false
messageLength = 0
}
}
}