bufio readbytes缓冲区大小

时间:2017-11-08 22:34:31

标签: go network-programming

我试图了解bufio ReadBytes收到大数据包时的行为。我在unix机器的eth0上运行一个简单的Golang TCP服务器,MTU = 9001。客户端是一个单独的机器(不直接连接到服务器)正在运行eth0上的python客户端程序,MTU = 1500。我的客户端python程序正在尝试发送一些大型数据包,这些数据包在客户端计算机中按预期分段,并以最大TCP MSS = 1440的IP数据包发送。提升一下,一切都很好。数据包到达服务器机器,我希望服务器机器在OSI Layer4重新组装数据包。所以,根据我的理解,我的Golang套接字缓冲区应该有一个大的数据包(已经重新组装)。我的Golang服务器程序使用bufio.ReadBytes('\ x04')来读取消息中的EOT字符。我的客户端程序明确地将EOT字符添加到每个数据包的有效负载的末尾。

在服务器中,我看到收到的包大小不一致。根据ReadBytes()的官方文档,它应该读取输入缓冲区中的所有数据,直到读入'delim'字符。我无法理解最大值。用于阅读器对象的bufio包中的缓冲容量,并且非常感谢任何人的帮助。

我的客户端程序代码段:

n_int_digits = function(x) {
  result = floor(log10(abs(x)))
  result[!is.finite(result)] = 0
  result
}

服务器程序代码段:

while True:
    l = random.randint(1400, 10000)
    data=("t"*l + '\x04').encode()
    try:
        if sock.send(data)==0:
            print("Server closed connection")
        else:
            print("Data send done. Intended length=", l, " bytes")
    except:
       print ("Exception when sending data. Trace=" + traceback.format_exc())
    time.sleep(10)
    sock.close()

从客户端发送到服务器的一个示例数据包:

    来自客户的
  1.   

    完成数据发送。预期长度= 8267字节

    => 8268字节,包括尾随EOT字符。

  2. 服务器上的
  3.   

    2017/11/08 21:55:42.551604 Recvd Bytes count = 1440

         

    2017/11/08 21:55:42.561897 Recvd Bytes count = 4096

         

    2017/11/08 21:55:42.569405 Recvd Bytes count = 2732

    => 3个不同的ReadBytes()被触发消耗8268个字节。

    =>第一次和第二次调用返回不同大小的数据。如果有一个单独的常量缓冲区用作bufio的输入缓冲区,我希望它们是相同的。

  4. 请问这里有什么帮助吗?

1 个答案:

答案 0 :(得分:1)

ReadBytes方法读取的数据量不受bufio.Reader读取缓冲区大小的限制。

问题不在于缓冲,而在于i / o超时。 ReadBytes函数读取,直到在底层io.Reader上找到或读取分隔符时返回错误。在问题中给出的示例中,ReadBytes在读取整个消息之前返回了两次i / o超时错误:

ReadBytes 
  read 1440 bytes
  timeout on read to underlying io.Reader, return error
ReadBytes
  read 4096 bytes
  timeout on read to underlying i.Reader, return error
ReadBytes
  read 2732 bytes to EOT
  return success

通过增加或消除阅读截止日期来解决问题。例如:

conn.SetReadDeadline(time.Now().Add(time.Second))

这是一个更简单的服务器应用程序版本,可以按预期工作。在此示例中删除了读取截止日期。

func main() {
    ln, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatal(err)
    }
    conn, err := ln.Accept()
    if err != nil {
        log.Fatal(err)
    }
    reader := bufio.NewReader(conn)
    for {
        buf, err := reader.ReadBytes('\x04')
        if err != nil {
            log.Fatal(err)
        }
        log.Printf("Received %d bytes\n", len(buf))
    }
}