Вопрос

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

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

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

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

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

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

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

Это было полезно?

Решение

Вопрос 1:полезны ли DBS для хранения таких данных, и как это сделать?

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

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

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

Для вашего приложения я бы выбрал Наследование конкретных таблиц дизайн.

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

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

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

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

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

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

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

Другие советы

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

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

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

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

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

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

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

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

Несмотря на то, что вы заявили, что отношений 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 для каждого поля в данном пакете.Это должно дать вам большую часть информации, необходимой для обработки произвольного фрагмента двоичных данных в вышеупомянутой схеме хранения пакетов.

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

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

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

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

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

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

  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, где вы помечаете определенные столбцы как «индексируемые», и индексы создаются поверх них при создании таблиц.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top