#SNMP 入门:一个开源 SNMP 实现
本文介绍了 #SNMP 及其使用方法,包括如何利用它来完成 SNMP 操作,例如管理支持 SNMP 的设备。
引言
#SNMP (SharpSNMP) Suite 是一套免费的 SNMP 工具,基于开源库,专为以 Microsoft .NET/Xamarin Mono 平台为目标的开发者而设计。它采用 C# 开发,也可用于 VB.NET、Delphi Prism 和许多其他编程语言。
本文在 MIT 许可下发布(因此本文所示示例代码也在此许可下发布)。
背景
.NET Framework 从一开始就完全支持基于 TCP/IP 的套接字编程。然而,由于 .NET Framework 基类库中没有专门针对 SNMP 的类,开发人员不得不依赖非常昂贵的三方库。市面上也有一些免费解决方案,但它们要么缺乏 SNMP v3、MIB 支持或其他高级功能。我在 2007 年的一篇博文中列出了更多信息,如果您想深入了解。
2008 年 4 月,我发布了一个名为 #SNMP 的开源项目来解决这个问题,因为我相信通过协作可以实现更好的解决方案,从而惠及所有需要足够好的免费解决方案的人。经过 4 年多的发展,该库已发展到目前的规模,拥有足够强大的库和许多有用的示例项目。
项目主页位于 CodePlex,源代码位于 GitHub。请注意,代码库被拆分成不同的模块,并在不同的许可下发布,正如 KB600012 中所述。
#SNMP 主要可在 Windows/.NET 平台上使用,例如 Windows XP/Windows Vista/Windows 7 和 Windows Server 操作系统,支持 .NET Framework 3.5/4.0/4.5。作为纯 .NET 代码库,它已成功移植到 Windows CE/.NET CF、Mono、MonoTouch 以及 Mono for Android。使用库
该 文档包包含一个 SandCastle 生成的帮助文件,可用于快速浏览 #SNMP 库(Lextm.SharpSnmpLib.*.dll)中提供的所有类。
以下是将一些 SNMP 操作(GET、SET 等)转换为 #SNMP 函数调用的示例:
GET 操作
以下代码展示了如何向位于 192.168.1.2 的 SNMP 代理发送 SNMP v1 GET 消息,并查询 OID 1.3.6.1.2.1.1.1.0,
var result = Messenger.Get(VersionCode.V1,
new IPEndPoint(IPAddress.Parse("192.168.1.2"), 161),
new OctetString("public"),
new List<Variable>{new Variable(new ObjectIdentifier("1.3.6.1.2.1.1.1.0"))},
60000);
如果在 60 秒(1 分钟)内未收到回复,此操作将超时并引发异常(TimeoutException
)。如果发生任何错误,则可以捕获 ErrorException
。所有 #SNMP 异常都继承自 SnmpException
。
返回的结果是一个列表,与发送的 Variable
对象列表匹配。此列表中的 Variable
包含 OID 的值。
SET 操作
以下代码展示了如何向位于 192.168.1.2 的 SNMP 代理发送 SNMP v1 SET 消息,并将 OID 1.3.6.1.2.1.1.6.0 的值设置为“Shanghai”,
var result = Messenger.Set(VersionCode.V1,
new IPEndPoint(IPAddress.Parse("192.168.1.2"), 161),
new OctetString("public"),
new List<Variable>{new Variable(new ObjectIdentifier("1.3.6.1.2.1.1.6.0"), new OctetString("Shanghai"))},
60000);
GET-NEXT 操作
以下代码展示了如何向位于 192.168.1.2 的 SNMP 代理发送 SNMP v1 GET-NEXT 消息,并查询 OID 1.3.6.1.2.1.1.1.0,
GetNextRequestMessage message = new GetNextRequestMessage(0,
VersionCode.V1,
new OctetString("public"),
new List<Variable>{new Variable(new ObjectIdentifier("1.3.6.1.2.1.1.6.0"))});
ISnmpMessage response = message.GetResponse(60000, new IPEndPoint(IPAddress.Parse("192.168.1.2"), 161));
if (response.Pdu().ErrorStatus.ToInt32() != 0)
{
throw ErrorException.Create(
"error in response",
receiver.Address,
response);
}
var result = response.Pdu().Variables;
GET-BULK 操作
以下代码展示了如何向位于 192.168.1.2 的 SNMP 代理发送 SNMP v2 GET-BULK 消息,并查询 OID 1.3.6.1.2.1.1.1.0,
GetBulkRequestMessage message = new GetBulkRequestMessage(0,
VersionCode.V2,
new OctetString("public"),
0,
10,
new List<Variable>{new Variable(new ObjectIdentifier("1.3.6.1.2.1.1.6.0"))});
ISnmpMessage response = message.GetResponse(60000, new IPEndPoint(IPAddress.Parse("192.168.1.2"), 161));
if (response.Pdu().ErrorStatus.ToInt32() != 0)
{
throw ErrorException.Create(
"error in response",
receiver.Address,
response);
}
var result = response.Pdu().Variables;
Walk 操作
Walk 不是一个原子操作。这意味着它利用了几个 GET-NEXT(SNMP v1 walk)或 GET-BULK(v2 及以上版本)操作。以下代码展示了如何在位于 192.168.1.2 的 SNMP 代理上从 1.3.6.1.2.1.1 开始执行 walk 操作,
var result = new List<Variable>();
Messenger.Walk(VersionCode.V1,
new IPEndPoint(IPAddress.Parse("192.168.1.2"), 161),
new OctetString("public"),
new ObjectIdentifier("1.3.6.1.2.1.1"),
result,
60000,
WalkMode.WithinSubtree);
返回的结果包含此 SNMP 代理中位于 1.3.6.1.2.1.1 树节点下的所有可用 OID(作为 Variable
)的列表。
#SNMP 支持两种 walk 模式:Default
和 WithinSubtree
。
Messenger.Walk
是基于 GET-NEXT 构建的。请注意,如果设备支持 SNMP v2,则应使用 Messenger.BulkWalk
,因为它基于 GET-BULK 构建并提供更好的性能。
var result = new List<Variable>();
Messenger.BulkWalk(VersionCode.V2,
new IPEndPoint(IPAddress.Parse("192.168.1.2"), 161),
new OctetString("public"),
new ObjectIdentifier("1.3.6.1.2.1.1"),
result,
60000,
10,
WalkMode.WithinSubtree,
null,
null);
TRAP 操作
通常是 SNMP 代理发送 TRAP 消息。以下代码展示了如何从 192.168.1.2 向位于 192.168.1.3 的 SNMP 管理器发送一个空的 SNMP v1 TRAP 消息,
Messenger.SendTrapV1(new IPEndPoint(IPAddress.Parse("192.168.1.3"), 162),
IPAddress.Parse("192.168.1.2"),
new OctetString("public"),
new ObjectIdentifier("1.3.6.1.2.1.1"),
GenericCode.ColdStart,
0,
0,
new List<Variable>();
SNMP v2 及以上版本引入了简化的 TRAP v2 消息,
Messenger.SendTrapV2(0,
VersionCode.V2,
new IPEndPoint(IPAddress.Parse("192.168.1.3"), 162),
new OctetString("public"),
new ObjectIdentifier("1.3.6.1.2.1.1"),
0,
new List<Variable>());
INFORM 操作
通常是 SNMP 代理发送 INFORM 消息。以下代码展示了如何向位于 192.168.1.3 的 SNMP 管理器发送一个空的 INFORM 消息,
Messenger.SendInform(0,
VersionCode.V2,
new IPEndPoint(IPAddress.Parse("192.168.1.3"), 162),
new OctetString("public"),
new ObjectIdentifier("1.3.6.1.2.1.1"),
0,
new List<Variable>(),
2000,
null,
null);
管理器应向此 INFORM 消息发送回复,否则会发生 TimeoutException
。
为了帮助您理解如何使用 #SNMP 库提供的 API,您可以在 源代码包的 Samples 文件夹中找到更多示例项目。C# 和 VB.NET 示例均可用。
关注点
上述示例应能让您初步了解使用 #SNMP API 执行常见 SNMP 操作的简便性。
我计划撰写更多关于高级用法的文章,例如编译 MIB 文档、SNMP v3 操作以及大型示例,如 #SNMP Compiler/Browser/Agent。
历史
2013 年 6 月 9 日:二进制文件已升级到 8.0 版本。
2012 年 10 月 3 日:添加了更多操作和示例代码。
2012 年 10 月 2 日:修订了开源许可描述。
2012 年 9 月 30 日:本文首次发布。