【问题标题】:Packet capture to database?数据包捕获到数据库?
【发布时间】:2009-05-29 23:22:50
【问题描述】:

我是数据库/PC应用程序方面的完全新手,请原谅我的无知。

我想实时捕获数据包到数据库,以便多个应用程序能够监控通过来自 PLC 的 udp 数据包返回的物理 I/O 数据,我有几个问题。

从长远来看,它需要跨平台,但目前我在 Windows 中使用 C# 数据包捕获库。关于数据库类型 MySQL 与 SQlite 的任何建议?

每秒约 1500 个 200 字节的数据包,每秒插入 1500 次数据包是否可行?我已经读到 SQlite 在并发性方面存在一些问题,如果我有一个应用程序以 25-50 毫秒的延迟以每秒 10 次查询数据库中的数据包数据 - 这可行吗?

我希望任何时候“只”需要在数据库中存储 20MB 左右的数据。数据库可以强制只在内存中运行吗?写入数据包数据时,能否将数据包(字节数组)写入一个语句而不是迭代插入每个字节/字?我想我可以把它变成一个字符串,但我希望这样几乎不可能以任何速度查询。在我简要查看的任何数据库中,我都没有看到任何提及“字节数组类型”之类的东西。 FWIW 所有数据都将发送到静态 IP 上的专用 NIC。数据包是顺序的(我知道 UDP 不能保证它,但我还没有见过有问题的数据包)如果数据库支持数组类型,我可以轻松地遍历数据。 - 很好,没有随机搜索?

感谢您花时间阅读本文。

鲍勃

【问题讨论】:

    标签: c# .net database


    【解决方案1】:

    您在关系数据库中为此寻找的感知优势是什么?既然你说你不太喜欢数据库,这里简要介绍一下为什么选择 SQL 的常见原因,也许它可以帮助你澄清你的要求和你的选择:

    1. 可查询性。如果您想为 rich 搜索公开数据,其中包括过滤记录、排序结果、聚合计算的选项,那么 SQL 数据库确实提供了这样的功能。他们不是免费的。为了加快搜索速度,数据库引擎必须将部分数据复制到多个索引中,这会增加插入/更新时间,因为必须维护所有这些索引。
    2. 可恢复性。数据库可以确保数据在发生崩溃时保持一致状态。使用预写日志或版本更新,他们编写更改的方式比确保客户在他的语句返回给他时所做的更改是持久的(为了简单起见,我省略了一堆细节)。
    3. 一致性。通过隔离用户之间的更改,直到他们明确提交一组相关操作,数据库始终向查看者公开一致的状态。为此,数据库必须部署锁定或版本控制。
    4. 可扩展性。数据库可以负责维护非常大的数据集,比进程可行的地址空间大得多。他们将使用缓冲池来缓存热页并管理底层文件偏移量到内存地址的映射以及从磁盘读取和写回更改所需的所有 I/O。它们还将多个文件显示为一个统一的存储区域,从而超过了操作系统文件大小限制(如果有的话)。
    5. 互操作性。其他进程可以使用标准库(即 ODBC、ADO 等)和语言 (SQL) 对数据进行操作,因此无需开发自定义库/访问 API。

    现在,您的场景需要这些吗?还有什么我遗漏的吗?我问这些问题是因为您想要实现的目标并非微不足道。您可以相对轻松地实现每秒 1500 次插入,但要做到这一点要困难得多并且提供不错的读取性能。此外,关系数据库提供的大部分功能(一致性、可恢复性、可伸缩性)似乎都不是您的目标。有许多产品专门针对内存中的细分市场进行了调整,这些产品比您从典型的面向磁盘的关系数据库中获得的产品要快得多。

    【讨论】:

    • 我同意他实际上可能不需要关系数据库。但正如您所说,该模型的好处(例如可恢复性和互操作性)似乎确实相关。
    • 谢谢 Remus... 我添加了一条评论,但它似乎已被删除。好的,然后.. 快速 #1 和 #5 - 无需 API 等即可与数据交互。正如您提到的那样
    • Matthew 已经为您提供了一些关于 MySQL 和 SQLite 的建议。您可以看一下 SQL CE,因为它与 CLR:msdn.microsoft.com/en-us/library/ms174461.aspx 甚至 SQL Express 集成得非常好。这不是 MySQL 或 SQLite 的任何东西;)
    【解决方案2】:

    编辑:我忘了你在用 C# 工作。

    首先,您打算从多台计算机上查询数据库吗?如果是这样,你会想要使用 MySQL。否则,SQLite 可能是一个不错的选择。但请注意,多个 C# 应用程序和内存数据库可能需要 MySQL。如果您选择 MySQL,请使用MySQL Connector/NET。对于 SQLite,有 System.Data.SQLite(我已将其用于 WinForms 应用程序并且可以推荐)。

    您说每个语句需要执行 1500 200 字节插入语句。 SQLite reports 每秒可以完成 50,000 次。关键的警告是,这是指原始插入,而不是事务。提交事务会减慢您的速度,因为这通常意味着刷新到磁盘。

    SQLite(参见 In-Memory Databases)和 MySQL(参见 MEMORY (HEAP) Storage Engine)都可以使用内存数据库。但是,对于 SQLite,这可能会破坏您让“多个应用程序”访问它的目标。使用 SQLite,您可以通过一种未记录的方式(并且“不保证在未来的 SQLite 版本中工作”)可以共享内存数据库(例如,使用共享内存)。在prior SO question 中进行了讨论;另请参阅 SQLite 主要作者的linked mail message。请注意,如果您坚持使用托管代码,则可能无法共享 SQLite 内存数据库。您绝对可以在多个客户端之间共享一个 MySQL 内存数据库。

    使用任一 C# 客户端,您都应该能够将整个数据包插入到带有 DbParameter 的单行中(即 SQLiteParameter 或 MySqlParameter)。请特别注意 Value 和 Size 属性。

    我认为您不需要任何“数组类型”。您可以简单地拥有一个递增的主键(INTEGER PRIMARY KEY)列和一个数据包内容列(BLOB 或 TEXT)。我不确定哪一个 BLOB 或 TEXT 将为您提供 SQLite 的最佳性能。您的 SQLite 架构可能看起来像

    CREATE TABLE packets ( id INTEGER PRIMARY KEY, packet BLOB);
    

    然后,您可以轻松选择例如一定范围内的主键数据包。当然,您可以添加一个日期时间列,但这需要索引。对于 MySQL,它会是这样的:

    CREATE TABLE packets ( id INTEGER PRIMARY KEY, packet VARCHAR(200)) ENGINE=MEMORY;
    

    我希望这会有所帮助。请记住,分析是确定哪些内容适合您的应用的最佳方式。

    【讨论】:

    • 马修,我再次输入了一个冗长的回复,谢谢你,但它现在似乎消失了?这些应用程序将与数据库在同一台机器上运行。感谢您的帮助。
    • 在这种情况下,这可能取决于您是否决定采用内存中的路线。如果你使用磁盘,SQLite 可能会比 MySQL 更简单,在内存中。
    【解决方案3】:

    libpcap、wireshark 循环文件

    环顾四周,玩一下wireshark,看看它是如何达到与你相似的结果的。

    【讨论】:

    • 这如何以任何方式回答这个问题?
    • 谢谢。我一直在使用 Wireshark 来观察和破译数据包数据和标头.. 效果很好,但我一直在 PERL 脚本上试图让它捕获到数据库。我遇到的麻烦与依赖相关..找到了一些带有 ppm 链接的好教程,但在 Net::Ethernet 丢失时一直失败...我能找到的最接近的包类似于 Address::Ethernet (我忘记了)我正在做所有事情在 Windows 中使用 ActiveState 5.10?所以也许包名没有直接相关......最后放弃了。
    猜你喜欢
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多