當來自先前連接的訊息的一部分轉到下一條訊息時,我不小心發現了一個錯誤。
我有一個帶客戶端的基本服務器。我已經洗掉了所有錯誤處理以避免使示例過于臃腫。
此外,我已經替換了一些Printf's ,time.Sleep因為我沒有機會及時斷開連接以重現錯誤,因為它讀取資料的速度太快了。
“包”是一個簡單的結構,其中前 4 個位元組是長度,然后是內容。
客戶端代碼:
package main
import (
"encoding/binary"
"fmt"
"net"
)
func main() {
conn, _ := net.Dial("tcp", "0.0.0.0:8081")
defer conn.Close()
str := "msadsakdjsajdklsajdklsajdk"
// Creating a package
buf := make([]byte, len(str) 4)
copy(buf[4:], str)
binary.LittleEndian.PutUint32(buf[:4], uint32(len(str)))
for {
_, err := conn.Write(buf)
if err != nil {
fmt.Println(err)
return
}
}
}
服務器代碼:
package main
import (
"encoding/binary"
"fmt"
"net"
"sync"
"time"
)
func ReadConnection(conn net.Conn, buf []byte) (err error) {
maxLen := cap(buf)
readSize := 0
for readSize < maxLen {
// instead of Printf
time.Sleep(time.Nanosecond * 10)
readN, err := conn.Read(buf[readSize:])
if err != nil {
return err
}
readSize = readN
}
return nil
}
func handleConnection(conn net.Conn, waitGroup *sync.WaitGroup) {
waitGroup.Add(1)
defer conn.Close()
defer waitGroup.Done()
fmt.Printf("Serving %s\n", conn.RemoteAddr().String())
var packageSize int32 = 0
int32Buf := make([]byte, 4)
for {
// read the length
conn.Read(int32Buf)
packageSize = int32(binary.LittleEndian.Uint32(int32Buf))
// assuming the length should be 26
if packageSize > 26 {
fmt.Println("Package size error")
return
}
// read the content
packageBuf := make([]byte, packageSize)
if err := ReadConnection(conn, packageBuf); err != nil {
fmt.Printf("ERR: %s\n", err)
return
}
// instead of Printf
time.Sleep(time.Nanosecond * 100)
}
}
func main() {
//establish connection
listener, _ := net.Listen("tcp", "0.0.0.0:8081")
defer listener.Close()
waitGroup := sync.WaitGroup{}
for {
conn, err := listener.Accept()
if err != nil {
break
}
go handleConnection(conn, &waitGroup)
}
waitGroup.Wait()
}
因此,由于某種原因,int32Buf從前一個訊息 (d, k) 接收最后 2 個位元組和長度的前 2 個位元組,從而產生[107, 100, 26, 0]位元組切片,當它應該是[26, 0, 0, 0]. 當然,其余資料包含剩余的兩個零:

uj5u.com熱心網友回復:
conn.Read(int32Buf)
您需要檢查 conn.Read 的回傳值并將其與您的期望進行比較。您在代碼中假設 conn.Read 將始終完全填充給定的 4 位元組緩沖區。
這個假設是錯誤的,即它實際上可能讀取的資料更少。具體來說,它可能只讀取 2 個位元組,在這種情況下,您最終會\x1a\x00\x00\x00在緩沖區中得到仍然轉換為 26 的訊息長度。只有訊息的前 2 個位元組實際上是長度的最后 2 個位元組,它們是不包括在最后一次閱讀中。這意味著在讀取 26 個位元組后,它不會讀取完整的訊息。2 個位元組是合法的,將包含在下一條訊息中 - 這就是您觀察到的。
要確保讀取緩沖區的確切大小,請檢查 conn.Read 的回傳值或使用io.ReadFull。完成此操作后,它按預期作業(來自評論):
好的,現在它完美運行
那么為什么這只發生在新連接的背景關系中呢?可能是因為另一個連接導致的額外負載稍微改變了行為,但已經足夠顯著了。盡管如此,這些不是從不同連接讀取的資料,而是來自當前連接的資料,這與問題中的描述相反。這可以通過對不同的客戶端使用不同的訊息來輕松檢查。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/515793.html
標籤:插座去tcp
