问题描述: 在我的应用程序中,我必须以特定格式呈现数据包的内容。一个例子:
示例 任何打包的二进制数据,例如:4字节标题,4字节类型(具有预定义含义的类型代码),然后是源地址,目标地址等。
以前,我做了家庭烹饪的实现,将数据存储在二进制文件中(固定记录长度允许快速查找),但随着时间的推移,我意识到我正在发明某种数据库。例如,我正在为非常大的数据文件实现我自己的高效二进制存储格式。我也在实现自己的索引,以便在某些字段上快速运行搜索。我认为真正的数据库(甚至是简单的SQLite)可以使这些内容变得非常简单。
问题#1:是用于存储此类数据的数据库,应如何处理?请注意,这里没有1对多,多对多的映射和其他高级内容,它只是一个简单的数据包序列,具有一定的内部结构,我想向用户显示并让他与之交互(即搜索某某领域)。
问题#2:现在假设用户自己可以指定数据包的格式,即在配置文件中:每个字段的长度,类型,值的含义(如果是一个枚举)等等。如何为此扩展数据库支持的实现?用户应该定义数据库模式吗?配置文件是否应自动转换为此架构? ORM?
问题#3:更高级......现在假设数据包的长度和内容可能不同。即,对于类型#2包,有一些字段,类型#3,一些其他字段,依此类推。但我仍然喜欢我的应用程序来处理它,很好地显示所有内容,并允许用户指定配置文件中的格式。怎么做?
提前致谢。
答案 0 :(得分:1)
一个简单的规则是:如果要查询数据,那么它应该是数据库中表中的离散字段。如果没有,你可以存储BLOB并完成它。
那就是说,如果你想从BLOB中获取“元数据”,并且索引THAT,那么你也可以很容易地做到这一点。
如果您的数据类型与数据库可以支持(或者可以准确转换)的数据类型一致,那么可以有一些价值将BLOB扩展到其组成部分,这些部分可以很好地映射到数据库列。
定义“动态表”(可以轻松完成)的问题不在于表的定义,而在于表的潜在变化。正在改变的表(即添加或删除的列等)在更改期间往往不可用。不是100行的问题。数百万行的真正问题。
如果数据定义是相当静态的,那么创建一个允许用户描述BLOB的映射工具,然后使用该定义创建一个兼容的表并在导入期间适当地转换BLOB。
对于“不同类型的不同行”,您仍然可以将数据填充到单个表中。某些行与其他行相比具有“未使用”列,每行都按类型标识。如果你有很多行定义和很多方差,那么你会浪费很多浪费的空间。然后,您可能希望为每个行类型创建一个表,以及一个包含行类型的主表和对实际表中实际行的引用。如果您关心原始数据包之间的关系,那么您只需要这个主表(然后您可以将它们存储在收据顺序中,比如说等)。
真的,这一切都归结为你有多少数据,你有多少期望,你想做多少工作与你已经完成的工作量等等。
答案 1 :(得分:1)
问题#1:DB是否有用 存储这些数据,应该怎么做 完成?
当然,数据库对此应用程序很有用。您可以实现自己的专用数据存储,也许它对您的特定应用程序更有效,因为您可以为该专业化设计它。关系数据库更通用,但您可以通过使用数据库来避免数周或数月的开发时间。
我今天早些时候回答了另一个关于如何处理可扩展类型的问题,其中每个新子类型都有自己独特的属性集。
“product table, many kind of product, each product have many parameters”。
对于您的应用,我会选择Concrete Table Inheritance设计。
问题#2:现在假设用户 他自己可以指定他的格式 数据包,即在配置文件中: 每个字段的长度,类型, 它的价值意味着什么(如果是 枚举)等。我如何能 扩展DB支持的实现 这个?
我假设数据包类型的数量相对较少,然后插入许多数据包具有几乎相同的结构。因此,您应该使用数据库管理元数据的能力。我会为每个新的数据包类型定义一个附加表。
我还会将数据包“爆炸”存储,因此数据包的每个字段都存储在一个单独的数据库列中。这样,您可以单独索引每列,以支持高效搜索。
您还可以定义约束,以便某些字段是必填字段(NOT NULL
)或其值受查找表约束。同样,利用数据库的功能来使用元数据来强制实现一致的结构。
SQL已经支持一种标准的声明性语言,用于指定具有数据类型,约束等的字段。为什么要开发一种不同的语言,然后将其转换为SQL?
问题3:更高级......现在 假设数据包可以 长度和内容各不相同。
给定数据包类型中可选的字段应允许相应列中的NULL
。
答案 2 :(得分:1)
您可能希望考虑的另一个选项是Berkeley DB或其中一个克隆。 BDB相当低级,没有SQL。它几乎是一个非常小,非常快的文件支持哈希表。它一直存在,并且在许多速度和简单性至关重要的地方使用。但是,您需要在顶部添加一些功能来完成您要完成的任务。
答案 3 :(得分:1)
尽管您声明没有1-many关系,但有:)
我建议为数据包存储创建两个表。一个用于存储“报头”或“标量”信息,这些信息对于数据包是通用的,并且 - 虽然它可以定义存在什么数据 - 但不是存储在数据包中的实际数据。
您的第二个表将存储每个数据包的数据,每个字段值组合代表此表中的一行。例如,以下两个表:
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
中有一条记录。这应该为您提供了将大量二进制数据处理成上述数据包存储架构所需的大部分信息。
答案 4 :(得分:1)
我想到了三种方法。
sFlow和IPFlow可以传输一组有限的数据包内容。这可以直接记录到几个不同的数据库中。
另一个更有针对性的方法是编写一个非常简单的snort规则,例如源或目标地址。然后让snort捕获数据包的有效负载。这样,您只能获得所需的实际数据。例如,您可以只抓取数据包内的数据字段。例如密码等。
ngrep也可以直接获取选择性数据。
当然,如果您没有在服务器/工作站本身进行捕获,则每个都可能需要在端口上进行点击或监视会话。
答案 5 :(得分:0)
虽然我不是这个实现的忠实粉丝,但我们有一些软件基本上可以用于某些调用列表。从本质上讲,这就是他们的所作所为:
注意:我并不特别喜欢步骤4中的SQL注入含义。如果安全性设计不正确并且应用程序中任何用户输入字段的输入,动态创建表可能会导致一些后果没有正确清理,特别是如果此应用程序具有可供不受信任的呼叫者(即Internet)使用的界面。
使用此方法,您可以在创建表时创建所需的索引(可能在步骤1中有一列将某些列标记为“可索引”),并且在创建表时在其上创建索引