草庐IT

go - bufio readbytes 缓冲区大小

coder 2024-07-12 原文

我试图了解 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/

有关go - bufio readbytes 缓冲区大小的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. HBase Region 简介和建议数量&大小 - 2

    Region是HBase数据管理的基本单位,region有一点像关系型数据的分区。region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。Region的结构hbaseregion的大小设置默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。RegionSplit时机:当1个region中的某个Store下所有StoreFile

  3. ruby-on-rails - Ruby 中意外的大小写行为 - 2

    我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

  4. ruby - 改变替换的大小写 - 2

    我有以下内容:text.gsub(/(lower)(upper)/,'\1\2')我可以将\2替换为大写吗?类似于:sed-e's/\(abc\)/\U\1/'这在Ruby中可行吗? 最佳答案 查看gsub文档:str.gsub(模式){|匹配|block}→new_str在block形式中,当前匹配字符串作为参数传入,$1、$2、$`、$&、$'等变量将被适当设置。block返回的值将替换为每次调用的匹配项。"alowerupperb".gsub(/(lower)(upper)/){|s|$1+""+$2.upcase}

  5. ruby - Sinatra:哈希的未定义方法字节大小 - 2

    很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visitthehelpcenter.关闭9年前。我正在创建一个Sinatra应用程序,它采用上传的CSV文件并将其内容放入哈希中。当我像这样在我的app.rb中引用这个散列时:hash=extract_values(path_to_filename)我不断收到此错误消息:undefinedmethod`bytesize'forHash:0x007fc5e28f2b90#object_idfile:utils.rblocation:bytesiz

  6. ruby - 使2个数组大小相同 - 2

    2个数组的数组:a=[[1,2],[22,11],[18,9]]b=[[1,81]]用[0,0]填充第二个的最佳方法是什么,以便它们具有相同的大小? 最佳答案 b.fill(b.size..a.size-1){[0,0]} 关于ruby-使2个数组大小相同,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/29725615/

  7. ruby - 数组大小太大 - ruby - 2

    我收到“ArgumentError:数组大小太大”消息,代码如下:MAX_NUMBER=600_000_000my_array=Array.new(MAX_NUMBER)问题。Array.new函数在Ruby中的最大值是多少? 最佳答案 具有5亿个元素的数组的大小为2GiBytes,这取决于您使用的特定操作系统,通常是一个进程可以处理的最大值。换句话说:您的数组大于您的地址空间。因此,解决方案很明显:要么缩小数组(例如,将其分成block),要么扩大地址空间(在Linux中,您可以修补内核以获得3、3.5甚至4GiByte地址空间,

  8. ruby-on-rails - Textmate 'Go to symbol' 相当于 Vim - 2

    在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol

  9. ruby-on-rails - Rails 存在吗?不区分大小写 - 2

    Model.exists?("lower(email)=?",params[:email].downcase)返回错误:ArgumentError(参数数量错误(2代表0..1)):是否可以使用不区分大小写的匹配来执行exists?? 最佳答案 您需要做的就是:Model.exists?(["lower(email)=?",params[:email].downcase])它正在寻找一个参数,但您提供了两个。使用数组形式和查找式条件应该可以满足您的需求。 关于ruby-on-rails-

  10. ruby - 使用 Ruby 在数组中查找大小为 N 的所有子集 - 2

    给定一个数组['a','b','c','d','e','f'],我如何获得包含两个的所有子集的列表、三、四元素?我是Ruby的新手(从C#迁移过来),不确定“Ruby之道”是什么。 最佳答案 查看Array#combination然后是这样的:2.upto(4){|n|array.combination(n)} 关于ruby-使用Ruby在数组中查找大小为N的所有子集,我们在StackOverflow上找到一个类似的问题: https://stackoverf

随机推荐