#c #binary-data
#c #двоичные данные
Вопрос:
Я пишу приложение 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;
проблема в том, что у меня нет способа определить, подходит ли какой-либо из них к моему концу. Мне нужно проанализировать всю структуру перед подтверждением, но я не могу этого сделать из-за проблемы с заполнением
или я направляюсь в неправильном направлении, анализируя этот пакет?
Ответ №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: %ldn",
(long)amp;x.code - (long)amp;x,
(long)amp;x.seg - (long)amp;x,
(long)amp;x.sym - (long)amp;x,
(long)amp;x.type - (long)amp;x,
(long)amp;x.amtToday - (long)amp;x,
(long)amp;x.price - (long)amp;x
);
// How much space does the struct take up if we create an array for it?
foo y[2];
printf("offset: %ldn", (long)amp;y[1] - (long)amp;y[0]);
return 0;
}
Вывод:
code: 0, seg: 4, sym: 14, type: 40, amtToday: 48, price: 56
offset: 64
Смещения могут зависеть от архитектуры и используемого компилятора. Если вы можете редактировать C-программу, добавление явного дополнения к структуре может быть лучшим способом гарантировать одинаковые смещения в 32-разрядных и 64-разрядных системах.
Комментарии:
1. интересно — разве
type
поле, являющееся коротким, не занимает всего 2 байта? почему здесь требуется 8?2. Итак, интересная вещь здесь заключается в том, что это зависит не от «типа», а скорее от «amtToday». Поскольку amtToday является длинным, он всегда будет выровнен по 8 байтам. (если вы не используете 32-разрядную систему). Порядок элементов вашей структуры будет определять, насколько плотно ваша структура может быть упакована в памяти. Например, чередование коротких и длинных плохо с точки зрения пустой траты места. en.wikipedia.org/wiki /…
3. Спасибо! я посмотрю на статью