Хранение пакетов данных в базе данных - PullRequest
4 голосов
/ 28 марта 2009

Описание проблемы: В моем приложении я должен представить содержимое пакетов данных в определенном формате. Пример:

Пример Любые упакованные двоичные данные, например: 4-байтовый заголовок, 4-байтовый тип (коды типов имеют предварительно определенные значения), затем адрес источника, адрес назначения и т. Д.

Раньше я делал реализации домашнего приготовления, в которых данные сохранялись в двоичном файле (фиксированная длина записи позволяла быстро искать), но со временем я понял, что изобрел какую-то базу данных. Например, я реализую свой собственный эффективный двоичный формат хранения для очень больших файлов данных. Я также внедряю свою собственную индексацию, чтобы быстро выполнять поиск по некоторым полям. Я думаю, что настоящая БД (даже простой SQLite) может сделать все это прозрачно простым.

Вопрос № 1: полезны ли БД для хранения таких данных и как это должно быть сделано? Обратите внимание, что здесь нет отображений 1-ко-многим, многим-ко-многим и другим сложным вещам, это просто обычная последовательность пакетов с определенной внутренней структурой, которую я хочу показать пользователю и позволить ему взаимодействовать (т.е. искать определенным полем).

Вопрос № 2: Теперь предположим, что пользователь сам может указать формат своих пакетов, то есть в файле конфигурации: длину каждого поля, его тип, что означают его значения (в случае перечисление) и тд. Как мне расширить реализацию с поддержкой БД для этого? Должен ли пользователь определять схемы БД? Должен ли файл конфигурации автоматически переводиться в эти схемы? ORM?

Вопрос № 3: Еще более продвинутый ... Теперь предположим, что пакеты данных могут различаться по длине и содержанию. То есть, для пакетов типа # 2 есть поле, для типа № 3, некоторые другие поля и так далее. Но я все еще хотел бы, чтобы мое приложение справлялось с этим, отображало все красиво, а также позволяло пользователям указывать форматы в файлах конфигурации. Как это сделать?

Заранее спасибо.

Ответы [ 6 ]

1 голос
/ 12 августа 2010

На ум приходят три метода.

sFlow и IPFlow могут передавать ограниченный набор содержимого пакета. Это может быть зарегистрировано непосредственно в нескольких различных базах данных.

Другим более целенаправленным методом было бы написание очень простого правила фырканья, такого как адрес отправителя или получателя. Затем snort перехватывает полезную нагрузку пакетов. Таким образом, вы получите только те данные, которые вам нужны. Например, вы можете получить только поля данных внутри пакета. например пароль и т. д.

ngrep также может получать выборочные данные прямо с провода.

Конечно, для каждого из них может потребоваться сеанс касания или мониторинга порта, если вы не выполняете захват на самом сервере / рабочей станции.

1 голос
/ 02 апреля 2009

Несмотря на то, что вы заявили, что нет 1-много отношений, есть:)

Я бы рекомендовал создать две таблицы для хранения пакетов. Один для хранения «заголовочной» или «скалярной» информации, которая является общей для пакета и - хотя она может определять ЧТО присутствуют данные - не является фактическими данными, хранящимися в пакете.

Ваша вторая таблица будет хранить данные для каждого пакета, причем каждая комбинация значения поля представляет строку в этой таблице. Например, следующие две таблицы:

create table packet
(
    packet_id int identity(1, 1) primary key,
    destination varchar(50),
    sender varchar(50),
    packet_type_id int not null
)

create table packet_field
(
    packet_field_id int identity(1, 1) primary key,
    packet_id int not null references packet (packet_id),
    field_id int not null,
    data varbinary(500)
)

Очевидно, что эти две таблицы делают предположения о типе и размере хранимых данных и не являются исчерпывающими в том, что им нужно хранить. Тем не менее, эта фундаментальная структура позволит динамически определять форматы пакетов и представляет собой схему, которая легко индексируется (например, добавление индекса на packet_id+field_id в packet_field было бы просто).

Тогда все ваше приложение отвечает за распаковку пакета и сохранение его в вашей БД в этой схеме, а затем перепаковку (при необходимости).

Конечно, с этого момента вам понадобятся таблицы, в которых хранится фактический формат пакета. Что-то вроде ...

create table packet_type
(
    packet_type_id int identity(1, 1) primary key,
    name varchar(200) not null
)

create table packet_type_field
(
    field_id int identity(1, 1) primary key,
    packet_type_id int not null references packet_type (packet_type_id)
    field_offset int not null,
    name varchar(200) not null
)

Опять, очевидно, упрощенно, но это показывает основную идею. У вас будет одна запись в вашей таблице packet_type для каждого формата пакета и одна строка в packet_type_field для каждого поля данного пакета. Это должно дать вам большую часть информации, которая понадобится вам для обработки произвольного фрагмента двоичных данных в вышеупомянутой схеме хранения пакетов.

1 голос
/ 31 марта 2009

Другой вариант, который вы можете рассмотреть, это Berkeley DB или один из его клонов. BDB довольно низкий уровень, SQL не существует. Это очень маленькая и очень быстрая хеш-таблица с файловой поддержкой. Это было вокруг навсегда, и используется во многих местах, где скорость и простота имеют первостепенное значение. Однако вам нужно добавить некоторые функциональные возможности, чтобы делать то, что вы пытаетесь достичь.

1 голос
/ 31 марта 2009

Вопрос № 1: полезны ли БД для хранение таких данных, и как это должно быть сделано?

Конечно, база данных полезна для этого приложения. Вы можете реализовать собственное хранилище данных специального назначения, и, возможно, оно будет более эффективным для вашего конкретного приложения, поскольку вы можете спроектировать его для этой специализации. Реляционная база данных более универсальна, но вы можете избежать нескольких недель или месяцев разработки, используя базу данных.

Ранее сегодня я ответил на другой вопрос о том, как обрабатывать расширяемые типы, где каждый новый подтип имеет свой собственный набор атрибутов.

" таблица продуктов, многие виды продуктов, каждый продукт имеет много параметров ."

Для вашего приложения я бы выбрал Конкретное наследование .

Вопрос № 2: Теперь предположим, что пользователь сам можешь указать формат своего пакеты, то есть в файле конфигурации: длина каждого поля, его тип, что означают его значения (в случае перечисление) и тд. Как я расширить поддерживаемую БД реализацию для этот?

Я предполагаю, что количество типов пакетов относительно мало, а затем многие пакеты вставляются с почти одинаковой структурой. Поэтому вы должны использовать возможности базы данных для управления метаданными. Я бы определил дополнительную таблицу для каждого нового типа пакета.

Я бы также сохранял пакеты в разобранном виде, поэтому каждое поле пакета хранится в отдельном столбце базы данных. Таким образом, вы можете индексировать каждый столбец отдельно, чтобы обеспечить эффективный поиск.

Вы также можете определить ограничения, чтобы некоторые поля были обязательными (NOT NULL) или их значения ограничивались справочными таблицами. Опять же, используя возможности базы данных для использования метаданных для обеспечения согласованной структуры там, где это желательно.

SQL уже поддерживает стандартный декларативный язык для указания полей с типами данных, ограничениями и т. Д. Зачем разрабатывать другой язык, который вам затем придется переводить в SQL?

Вопрос № 3: Еще более продвинутый ... Сейчас предположим, что пакеты данных могут быть варьируется по длине и содержанию.

Поля, которые являются необязательными в данном типе пакета, должны разрешать NULL в соответствующем столбце.

1 голос
/ 31 марта 2009

Простое правило таково: если вы собираетесь запрашивать данные, то это должно быть дискретное поле в таблице в БД. Если нет, вы можете сохранить BLOB и покончить с этим.

Тем не менее, если вы хотите извлечь «метаданные» из BLOB-объекта и проиндексировать ТО, то вы также можете легко это сделать.

Если ваши типы данных согласуются с тем, что база данных может поддерживать (или может быть точно преобразована), может быть какое-то значение, когда BLOB разбирается с его компонентами, которые хорошо отображаются в столбцы БД.

Проблема с определением «таблиц на лету» (что можно легко сделать) заключается не столько в определении таблицы, сколько в ее возможном изменении. Таблицы, которые изменяются (то есть добавляется или удаляется столбец и т. Д.), Как правило, непригодны для использования во время изменения. Не проблема для 100 строк. Настоящая проблема для миллионов строк.

Если определения данных довольно статичны, то создайте средство сопоставления, которое позволит вашим пользователям описывать большой двоичный объект, и затем вы используете это определение для создания совместимой таблицы и соответствующего преобразования больших двоичных объектов во время импорта.

Что касается «разных строк разных типов», вы все равно можете поместить эти данные в одну таблицу. Некоторые строки имеют «неиспользуемые» столбцы по сравнению с другими, каждая строка идентифицируется по типу. Если у вас много определений строк и много различий, вы получите много потерянного пространства при этом. Затем вы можете захотеть перейти к наличию таблицы для каждого типа строки и основной таблицы, которая содержит типы строк и ссылки на реальные строки в реальных таблицах. Эта основная таблица понадобится вам только в том случае, если вы заботитесь об отношениях друг с другом исходных пакетов данных (тогда вы можете хранить их в порядке получения, скажем и т. Д.).

Действительно, все сводится к тому, сколько данных у вас есть, сколько вы ожидаете, сколько работы вы хотите сделать против того, сколько вы уже сделали и т. Д.

0 голосов
/ 30 марта 2009

Хотя я не большой поклонник этой реализации, у нас есть программное обеспечение, которое по сути делает это для некоторых списков вызовов. По сути, вот что они делают:

  1. Таблица с определениями столбцов - назовите ее tblColumnDefs. Эта таблица содержит столбцы, такие как «Имя», «Тип», «Длина» и «Описание»
  2. Основная таблица экземпляра (tblPacketNames). По сути, просто "PacketTypeID", "PacketName" и "Description" для каждого определяемого вами типа пакета
  3. Таблица определения экземпляра (для вас это будет tblPacketColumns). Эта таблица собирает предварительно определенные столбцы вместе, чтобы сформировать структуру данных, которую вы храните. Например, он может содержать «PacketTypeID», «ColumnNumber», «ColumnID». В базе данных говорит о нормализации, это таблица «многие ко многим», поскольку она сопоставляет столбцы с пакетами, которые их используют.
  4. Во второй базе данных (из-за динамических последствий SQL / внедрения этого шага) таблицы создаются динамически для хранения фактических данных. Например, если вы определили (в шагах 2/3) тип пакета с именем «PING», в вашей базе данных может быть таблица «PING» для хранения этих данных. Вы бы использовали tblPacketColumns, связанную с tblColumnDefs, чтобы выяснить, какие типы полей создавать и насколько они должны быть большими. В итоге вы получите набор таблиц, которые соответствуют определениям типа пакета из шага 3, используя столбцы из шага 1.

ПРИМЕЧАНИЕ. Мне не особо нравятся последствия внедрения кода SQL на шаге 4. Динамическое создание таблиц может привести к некоторым последствиям, если безопасность не разработана должным образом и вводится из любых полей, введенных пользователем в вашем приложении. не очищается должным образом, особенно если это приложение имеет интерфейс, доступный для ненадежных абонентов (например, Интернет).

Используя это, вы можете создавать индексы по своему усмотрению при создании таблиц (возможно, у вас есть столбец на шаге 1, где вы помечаете определенные столбцы как «индексируемые», и индексы создаются поверх них при создании таблиц). .

...