为了账号安全,请及时绑定邮箱和手机立即绑定

TCP 套接字:消息接收来自先前连接的消息的一部分

TCP 套接字:消息接收来自先前连接的消息的一部分

Go
慕尼黑8549860 2023-02-28 21:20:37
当来自上一个连接的消息的部分转到下一个消息时,我不小心发现了一个错误。我有一个带客户端的基本服务器。我已经删除了所有错误处理以避免示例过多膨胀。我也用 替换了一些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。完成此操作后,它会按预期工作(来自评论):

好的,现在它完美无缺

那么为什么这只发生在新连接的上下文中呢?可能是因为另一个连接导致的额外负载稍微改变了行为,但足够显着。不过,这些不是从不同连接读取的数据,而是与问题中的描述相反的当前连接读取的数据。这可以通过对不同的客户端使用不同的消息来轻松检查。


查看完整回答
反对 回复 2023-02-28
  • 1 回答
  • 0 关注
  • 41 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信