gpt4 book ai didi

go - bufio readbytes 缓冲区大小

转载 作者:数据小太阳 更新时间:2023-10-29 03:34:46 26 4
gpt4 key购买 nike

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

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

我的客户端程序片段:

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()

服务器程序片段:

reader := bufio.NewReader(conn)
readbuf := make([]byte, 1500)
err := io.EOF
for sockConnected {
conn.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
readbuf, err = reader.ReadBytes('\x04')
switch {
case err == io.EOF || err == io.ErrUnexpectedEOF:
log.Println("Socket closed. EOF / ErrUnexpectedEOF read in")
sockConnected = false
case err == nil:
//log.Println("No error on read")
case strings.HasSuffix(err.Error(), "i/o timeout"):
//log.Println("Timed out read")
default:
log.Println("Some other error occurred.Reason=" + err.Error())
}
if len(readbuf) == 0 {
continue
} else {
//log.Printf("Received from client=%v", string(readbuf))
log.Printf("Recvd Bytes count=%v", len(readbuf))
}
}

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

  1. 来自客户:

    Data send done. Intended length= 8267 bytes

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

  2. 在服务器上:

    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 字节。

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

这里有什么帮助吗?

最佳答案

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))
}
}

关于go - bufio readbytes 缓冲区大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47190864/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com