使用元编程在Go语言中解析网络协议

huangapple go评论79阅读模式
英文:

Parsing network protocols using meta-programming in Go

问题

在JavaScript(Node)中,我编写了一个模块,它接受字段及其类型的列表,并返回一个具有packunpack方法的对象。以下是打包和解包IPv4的代码:

var ipv4 = proto.add('struct', {
  name: 'IPV4',
  fields: {
    version:       'int:4',
    ihl:           'int:4',
    dscp:          'int:6',
    ecn:           'int:2',
    length:        'int:16',
    id:            'int:16',
    flags:         'int:3',
    offset:        'int:13',
    ttl:           'int:8',
    protocol:      'int:8',
    checksum:      'int:16',
    src:           'IPV4_ADDR',
    dst:           'IPV4_ADDR',
    // TODO: IPv4 OPTIONS
    options:       'raw'
  },
  $length: 'length'
});
//然后我可以这样做
ipv4.pack({ version: 4, ... }); //=> buffer
//和
ipv4.unpack(buffer); //=> { ... }

由于JavaScript是动态的,我可以元编程(合理地)优化packunpack函数。据我所了解,您不能在Go中动态创建函数,尽管使用reflect包似乎是可能的。这值得追求吗?或者使用reflect会太昂贵吗?

我希望避免为我想解析的每个网络协议编写类似这样的代码

英文:

In JavaScript (Node), I've written a module which accepts a list of fields and their types and returns an object with pack and unpack methods. Below is the code to pack and unpack IPv4:

var ipv4 = proto.add('struct', {
  name: 'IPV4',
  fields: {
    version:       'int:4',
    ihl:           'int:4',
    dscp:          'int:6',
    ecn:           'int:2',
    length:        'int:16',
    id:            'int:16',
    flags:         'int:3',
    offset:        'int:13',
    ttl:           'int:8',
    protocol:      'int:8',
    checksum:      'int:16',
    src:           'IPV4_ADDR',
    dst:           'IPV4_ADDR',
    // TODO: IPv4 OPTIONS
    options:       'raw'
  },
  $length: 'length'
});
//then I can do
ipv4.pack({ version: 4, ... }); //=> buffer
//and
ipv4.unpack(buffer); //=> { ... }

Since JavaScript is dynamic, I can meta-program (reasonably) optimised pack and unpack functions. From what I understand, you cannot dynamically create functions in Go, though it appears this would be possible using the reflect package. Is this worth pursuing? Or would it be too costly to use reflect?

I'm hoping to avoid writing code like this for every network protocol I wish to parse.

答案1

得分: 2

如果可以接受半动态解决方案,你可以参考为了提高速度而设计的许多用于 Golang 的 JSON 替代包。它们的方法是给结构体打上标签,然后运行一个工具(例如作为 make 配置的一部分)来为所需的类型生成 MarshalJSONUnmarshalJSON 方法。这显然比使用标签更快。

以下是一些帮助你的示例:

英文:

If can accept a semi-dynamic solution, you could take inspiration in the numerous JSON alternative packages for Golang that are designed for speed. Their approach is to tag a struct, then run a tool (as part of a make configuration for example) to generate the MarshalJSON and UnmarshalJSON methods for the desired types. Which is clearly faster than using tags.

Some examples to help you :

huangapple
  • 本文由 发表于 2014年8月6日 17:01:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/25156204.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定