当来自上一个连接的消息的部分转到下一个消息时,我不小心发现了一个错误。我有一个带客户端的基本服务器。我已经删除了所有错误处理以避免示例过多膨胀。我也用 替换了一些Printf,time.Sleep因为我没有机会及时断开连接来重现错误,因为它读取数据的速度太快了。“包”是一个简单的结构,前 4 个字节是长度,然后是内容。客户端代码:package mainimport ( "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 } }}因此,出于某种原因,int32Buf接收前一条消息 (d, k) 的最后 2 个字节和长度的前 2 个字节,从而产生[107, 100, 26, 0]字节切片,而它应该是[26, 0, 0, 0]. 当然,其余数据包含剩余的两个零:
1 回答
浮云间
TA贡献1829条经验 获得超4个赞
conn.Read(int32Buf)
您需要检查 conn.Read 的返回值并将其与您的预期进行比较。您在代码中假设 conn.Read 将始终完全填充给定的 4 字节缓冲区。
这个假设是错误的,即它实际上可能读取更少的数据。具体来说,它可能只读取 2 个字节,在这种情况下,您最终会\x1a\x00\x00\x00
在缓冲区中得到仍然转换为 26 的消息长度。只是,消息的前 2 个字节实际上是长度的最后 2 个字节不包括在最后一次阅读中。这意味着在读取 26 个字节后,它不会读取完整的消息。2 个字节是 leg 并将包含在下一条消息中 - 这就是您观察到的。
要确保读取缓冲区的确切大小,请检查 conn.Read 的返回值或使用io.ReadFull。完成此操作后,它会按预期工作(来自评论):
好的,现在它完美无缺
那么为什么这只发生在新连接的上下文中呢?可能是因为另一个连接导致的额外负载稍微改变了行为,但足够显着。不过,这些不是从不同连接读取的数据,而是与问题中的描述相反的当前连接读取的数据。这可以通过对不同的客户端使用不同的消息来轻松检查。
- 1 回答
- 0 关注
- 57 浏览
添加回答
举报
0/150
提交
取消