在 Go 中解析二进制数据包(来自 C)

Parsing a binary packet (from C) in Go

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

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-code 来计算偏移量:

#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-program,向结构添加显式填充可能是保证 32 位和 64 位系统上相同偏移量的最佳方式。