【问题标题】:Getting IP addresses from big nfcapd binary files从大型 nfcapd 二进制文件中获取 IP 地址
【发布时间】:2016-10-27 21:17:05
【问题描述】:

我需要从 nfcapd 二进制文件中获取有关源 IP 和目标 IP 的信息。问题在于文件的大小。我知道使用 io 或 os 包打开和读取非常大(超过 1 GB)的文件是不可取的。

这是我的黑客和草稿开始:

package main

import (
    "fmt"
    "time"
    "os"
    "github.com/tehmaze/netflow/netflow5"
    "log"
    "io"
    "bytes"
)

type Message interface {}

func main() {
    startTime := time.Now()
    getFile := os.Args[1]
    processFile(getFile)
    endTime := time.Since(startTime)
    log.Printf("Program executes in %s", endTime)
}

func processFile(fileName string) {
    file, err := os.Open(fileName)
    // Check if file is not empty. If it is, then exit from program
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }

    // Useful to close file after getting information about it
    defer file.Close()
    Read(file)
}

func Read(r io.Reader) (Message, error) {
    data := [2]byte{}
    if _, err := r.Read(data[:]); err != nil {
        return nil, err
    }
    buffer := bytes.NewBuffer(data[:])
    mr := io.MultiReader(buffer, r)
    return netflow5.Read(mr)
}

我想将文件拆分为具有 24 个流的块,并在使用 netflow package 读取后并发处理它。但我无法想象如何在除法期间不丢失任何数据的情况下做到这一点。

如果我遗漏了代码或描述中的某些内容,请修复我。我花了很多时间在网上搜索我的解决方案并考虑其他可能的实现方式。

我们将不胜感激任何帮助和/或建议。

文件具有以下属性(终端中的命令file -I <file_name>):

file_name: application/octet-stream; charset=binary

命令nfdump -r <file_name>之后的文件输出结构如下:

Date first seen          Duration Proto      Src IP Addr:Port          Dst IP Addr:Port   Packets    Bytes Flows

每个属性都在自己的列上。

更新 1: 不幸的是,由于二进制文件结构的差异,通过 nfcapd 将文件保存到磁盘后,使用 netflow 包解析文件是impossible。此答案由nfdump 贡献者中的one 给出。

现在唯一的方法是在 go 程序中从终端运行 nfdump,例如 pynfdump

未来的另一个possible解决方案是使用gopacket

【问题讨论】:

  • 这个 nfcapd 二进制文件的结构是什么?它实际上是一个结构合理的文本文件吗?您的问题是您不知道如何有效地读取文件,还是您还需要解析 IP 的帮助?
  • 我在 GitHub Gist 中找到了一个示例输出文件:gist.githubusercontent.com/asachs/bfbfebdb39b33a5ded61/raw/… 我假设您正在处理的是一个非常大的版本。
  • @HenryTK 我添加了有关文件的更多信息。我现在不知道如何有效地读取文件和解析 IP。我是 Golang 的新手。
  • 你为什么要创建一个 goroutine 来读取文件 go Read(file) ??好吧,我警告你,你的程序肯定不会做任何事情,main() 函数将结束,就是这样。
  • @YandryPozo 哦,对不起。这是错字

标签: go netflow


【解决方案1】:

IO 几乎总是解析文件时的限制因素,除非涉及大量计算,否则串行读取单个文件将是处理它的最快方法。

将文件包装在bufio.Reader 中并将其提供给Read 函数:

file, err := os.Open(fileName)
if err != nil {
    log.Fatal((err)
}
defer file.Close()

packet, err := netflow5.Read(bufio.NewReader(file))

解析完成后,如果需要单独处理块,则可以拆分记录。

【讨论】:

  • 无法如你想象的那样用 netflow 读取这个二进制文件。由于这个if statementgithub.com/tehmaze/netflow/blob/master/netflow5/packet.go#L62你不能一次读取整个文件。我的目标是单独阅读它以将流发送到 Unmarshall 数据。
  • @memu:如果 netflow 包不能解析它,你需要一些可以解析的东西。如果没有一些基本的解析,就无法分离二进制文件的各个部分。工作流程还是一样的,把文件包在bufio.Reader里,依次读取。
  • “连载阅读”是什么意思?它是否使用字节数组块读取?如果是这样,我应该选择哪种尺寸?
  • @memu:我的意思是从头到尾读取文件一次,而不尝试添加不必要的并发性。使用缓冲 IO 的关键在于它使大小无关紧要,您可以读取所需的大小。
  • @memu,同样,一般来说,当您受到 IO 的限制时,并发不会让您更快地读取文件。尝试同时读取文件的多个部分会导致更多随机 IO,这会显着降低吞吐量。并发不是并行,也不能神奇地让非并行的事情变得更快。 如果有大量计算要应用于从文件读取的独立隔离数据结构,那么特定计算可能会受益于并行性,但解析文件不是这种情况。
猜你喜欢
  • 2018-06-04
  • 2013-04-11
  • 2014-06-10
  • 1970-01-01
  • 1970-01-01
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多