【问题标题】:Parsing a binary packet (from C) in Go在 Go 中解析二进制数据包(来自 C)
【发布时间】:2020-11-04 12:24:50
【问题描述】:

我正在编写一个通过网络侦听 UDP 数据包并解析它们的 go 应用程序。

udp 数据包是用 C 语言编写的,结构定义(根据他们的文档)如下所示。 (请理解 C 和一般网络的新手)

typedef struct foo 
{
  int code;
  char seg[10];
  char sym[25];
  short type;
  long amtToday;
  long price;
  ...etc
} foo;

一个示例网络数据包如下所示

[233 3 0 0 99 100 101 95 102 111 0 0 0 0 55 52 51 57 0 69 69 68 49 48 50 48 74 65 78 50 48 50 49 0 0 58 254 127 0 0 1 0 166 58 254 127 0 0 255 255 255 255 255 255 255 255 32 232 141 0 0 0 0 0 0 135 166 58 254 127 0 0 ... etc]

简而言之,我无法在 sym 字段之后获取正确的值。

我阅读了一些关于 C 中的结构对齐的信息,并猜测我忽略了填充值。但是我对填充发生的位置有点困惑

是这个

typedef struct foo 
{
  int code;
  char seg[10];
  **char pad[6];**
  char sym[25];
  **char pad[7];**
  short type;
  long amtToday;
  long price;
  ...etc
} foo;

即在每个 char 字段之后添加填充

还是更像这样

typedef struct foo 
{
  int code;
  char seg[10];
  char sym[25];
  **char pad[1];**
  short type;
  long amtToday;
  long price;
  ...etc
} foo;

问题是我无法确定其中任何一个是否正确。我需要在确认之前解析整个结构 - 但由于填充问题而无法这样做

还是我在解析这个数据包时走错了方向?

【问题讨论】:

    标签: c binary-data


    【解决方案1】:

    让自己相信它是如何工作的最好方法可能是编写计算偏移量的 C 代码:

    #include <stdio.h>
    
    typedef struct foo
    {
        int code;
        char seg[10];
        char sym[25];
        short type;
        long amtToday;
        long price;
    } foo;
    
    int main() {
        // What are the memory offsets between individual struct members?
        foo x;
        printf(
            "code: %ld, seg: %ld, sym: %ld, type: %ld, amtToday: %ld, price: %ld\n",
            (long)&x.code - (long)&x,
            (long)&x.seg - (long)&x,
            (long)&x.sym - (long)&x,
            (long)&x.type - (long)&x,
            (long)&x.amtToday - (long)&x,
            (long)&x.price - (long)&x
        );
    
        // How much space does the struct take up if we create an array for it?
        foo y[2];
        printf("offset: %ld\n", (long)&y[1] - (long)&y[0]);
        return 0;
    }
    

    输出:

    code: 0, seg: 4, sym: 14, type: 40, amtToday: 48, price: 56
    offset: 64
    

    偏移量取决于架构和使用的编译器。如果您能够编辑 C 程序,则向结构添加显式填充可能是保证 32 位和 64 位系统上相同偏移量的最佳方法。

    【讨论】:

    • 有趣 - type 字段不是很短,只需要 2 个字节吗?为什么这里要 8 个?
    • 所以这里有趣的是,这不取决于“类型”,而是取决于“amtToday”。由于 amtToday 是一个 long,它总是 8 字节对齐。 (除非您使用的是 32 位系统)。您的结构成员的顺序将决定您的结构在内存中的压缩程度。例如,交替短和长在浪费空间方面是不好的。 en.wikipedia.org/wiki/…
    • 谢谢!我看看这篇文章
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 2011-10-02
    • 1970-01-01
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 2014-02-20
    相关资源
    最近更新 更多