tcp - Go:有效处理通过 TCP 接收的碎片数据

标签 tcp go buffer

我正在编写一个小型 tcp 服务器,它只用于读取数据、解析接收数据(动态长度帧)并处理这些帧。考虑以下代码:

func ClientHandler(conn net.Conn) {
    buf := make([]byte, 4096)
    n, err := conn.Read(buf)
    if err != nil {
        fmt.Println("Error reading:", err.Error())
        return
    }
    fmt.Println("received ", n, " bytes of data =", string(buf))
    handleData(buf)

这几乎就是我的代码的本质。我将 X 字节读入空缓冲区,然后处理数据。

问题发生在:

  1. 一帧数据比它试图从 tcp 连接读入的缓冲区大。在这种情况下,我无法处理数据,直到收到其余数据(但接收缓冲区已被之前的数据占用)。
  2. 当缓冲区包含一个半帧的数据时,我需要处理第一帧,同时保留不完整的帧供以后使用...在这种情况下,我需要从缓冲区中移除已处理的部分,然后移动不完整的部分,以便为框架的其余部分留出空间。

这两种情况都可能需要重新分配和复制数据,这可能是一项代价高昂的操作?此外,除了扩展缓冲区之外,我不知道如何处理大于缓冲区的帧......但是不断增加的缓冲区可能会导致性能问题和拒绝服务。最后但并非最不重要的一点是,我对 Golang 的标准库的了解不够好,无法知道是否有明确构建的包来处理这些情况。

所以我的问题是:

  1. 是否有处理这些情况的最佳实践?
  2. 是否有任何 golang 包可以为我完成部分或大部分工作?

谢谢。

最佳答案

byte slice 应该支持非常优化的大小调整(即保留比需要更多的字节,如果可以则不复制,呈指数增长,复制代码不是用 go 编写的,而是运行时的一部分,等等)。

因此您可以使用 append 并查看其工作原理。

另一种更惯用的方法是使用 bufio.Reader 来包装连接,它会自动处理所有这些。我已经在我编写的 tcp 服务器中使用它并且速度非常快。你只需要做:

r := bufio.NewReader(conn)

然后您可以读取直到分隔符或给定的字节数(如果您事先知道)。

关于tcp - Go:有效处理通过 TCP 接收的碎片数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22218838/

相关文章:

go - golang protobuf编译中指定基础包

c - 为什么即使在非规范模式下我仍然需要按 'Enter"才能让输入被读取和输出?

C memmove 相当于 for 循环 - 段错误

我可以使用 inet_pton 为我的 TCP 套接字服务器设置文本地址,例如 "device1.local"吗?

c++ - 使用 tcp 套接字复制损坏的管道错误

google-app-engine - 在本地运行 Go App Engine 应用程序。

go - 如何将数据库中的点坐标转换为GoLang中的点结构

c# - 如何将 C# 流式传输视频(图像)到 HTML5 客户端?

c++ - boost 客户端-服务器连接稳定性

java - 将 UDP 与 NIO 一起使用有什么意义?