利用C#开发基于snmpsharpnet基础的SNMP开发应用
由于项目的需要,需要使用SNMP来进行相关的开发,需要在我的程序中利用SNMP的Trap协议给指定的系统程序发送相关的设备数据信息, 使得其系统能够监控到设备的最新信息以及状态,对方只是提供了一个Java的例子,而我的程序是C#开发的,因此对这方面的知识进行了解学习,完成了相关的功能,本文有感于此,对SNMP方面做了一些开发总结,以求树碑到此一游,独乐不如众乐,邀兴趣之士猎奇探秘.
首先介绍标题的几个问题,SNMP是什么,snmpsharpnet又是什么,开发能解决什么问题?
SNMP是什么呢?
简单来说,SNMP主要就是一种特定的网络管理协议,用来获取设备相关信息的一种一些,复杂来讲,就很讲究了,我不在长篇大量介绍重复的内容,需要了解可以参考下面几篇博文:
SNMP介紹及命令
SNMP基础简介
snmpsharpnet又是什么呢?
http://www.snmpsharpnet.com/
,里面有很多C#使用例子及相关介绍。
有人也应用它来做了一些小应用,如博客:
c#开发snmp应用
这类开发能解决什么问题呢?
简单来讲,可以开发相关设备管理及监控的程序。
为了使用SNMP来进行调试及开发,需要在操作系统中安装SNMP服务(默认系统没有安装),安装和普通的安装Window组件一样的步骤,选定简单网络管理协议组件即可,安装后,在服务中启动SNMP服务即可,如下所示:
虽然启动了服务,不过要顺利访问,还需要对系统的社区名称及可以访问的IP地址做配置,否则一样无法取得计算机的相关设备信息,配置对话框是双击服务,打开属性对话框进行配置即可。
利用SNMPSharpNet组件来开发SNMP服务应用,省却了很多复杂的组装操作,非常方便,如获取指定机器的基本信息,可以通过
private
void
button1_Click(
object
sender, EventArgs e)
//
SNMP community name
OctetString community
=
new
OctetString(
"
public
"
);
AgentParameters param
=
new
AgentParameters(community);
param.Version
=
SnmpVersion.Ver1;
IpAddress agent
=
new
IpAddress(
"
192.168.0.50
"
);
//
Construct target
UdpTarget target
=
new
UdpTarget((IPAddress)agent,
161
,
2000
,
1
);
//
Pdu class used for all requests
Pdu pdu
=
new
Pdu(PduType.Get);
pdu.VbList.Add(
"
1.3.6.1.2.1.1.1.0
"
);
//
sysDescr
pdu.VbList.Add(
"
1.3.6.1.2.1.1.2.0
"
);
//
sysObjectID
pdu.VbList.Add(
"
1.3.6.1.2.1.1.3.0
"
);
//
sysUpTime
pdu.VbList.Add(
"
1.3.6.1.2.1.1.4.0
"
);
//
sysContact
pdu.VbList.Add(
"
1.3.6.1.2.1.1.5.0
"
);
//
sysName
//
Make SNMP request
SnmpV1Packet result
=
(SnmpV1Packet)target.Request(pdu, param);
if
(result
!=
null
)
{
//
ErrorStatus other then 0 is an error returned by
//
the Agent - see SnmpConstants for error definitions
if
(result.Pdu.ErrorStatus
!=
0
)
{
//
agent reported an error with the request
this
.txtContent.Text
+=
string
.Format(
"
Error in SNMP reply. Error {0} index {1} \r\n
"
,
result.Pdu.ErrorStatus,
result.Pdu.ErrorIndex);
}
else
{
//
Reply variables are returned in the same order as they were added
//
to the VbList
this
.txtContent.Text
+=
string
.Format(
"
sysDescr({0}) ({1}): {2} \r\n
"
,
result.Pdu.VbList[
0
].Oid.ToString(), SnmpConstants.GetTypeName(result.Pdu.VbList[
0
].Value.Type),
result.Pdu.VbList[
0
].Value.ToString());
this
.txtContent.Text
+=
string
.Format(
"
sysObjectID({0}) ({1}): {2} \r\n
"
,
result.Pdu.VbList[
1
].Oid.ToString(), SnmpConstants.GetTypeName(result.Pdu.VbList[
1
].Value.Type),
result.Pdu.VbList[
1
].Value.ToString());
this
.txtContent.Text
+=
string
.Format(
"
sysUpTime({0}) ({1}): {2} \r\n
"
,
result.Pdu.VbList[
2
].Oid.ToString(), SnmpConstants.GetTypeName(result.Pdu.VbList[
2
].Value.Type),
result.Pdu.VbList[
2
].Value.ToString());
this
.txtContent.Text
+=
string
.Format(
"
sysContact({0}) ({1}): {2} \r\n
"
,
result.Pdu.VbList[
3
].Oid.ToString(), SnmpConstants.GetTypeName(result.Pdu.VbList[
3
].Value.Type),
result.Pdu.VbList[
3
].Value.ToString());
this
.txtContent.Text
+=
string
.Format(
"
sysName({0}) ({1}): {2} \r\n
"
,
result.Pdu.VbList[
4
].Oid.ToString(), SnmpConstants.GetTypeName(result.Pdu.VbList[
4
].Value.Type),
result.Pdu.VbList[
4
].Value.ToString());
}
}
else
{
this
.txtContent.Text
+=
string
.Format(
"
No response received from SNMP agent. \r\n
"
);
}
target.Dispose();
}
运行后可以显示指定机器的基本信息,如下所示:
sysObjectID(1.3.6.1.2.1.1.2.0) (ObjectId): 1.3.6.1.4.1.311.1.1.3.1.2
sysUpTime(1.3.6.1.2.1.1.3.0) (TimeTicks): 46d 4h 14m 2s 320ms
sysContact(1.3.6.1.2.1.1.4.0) (OctetString):
sysName(1.3.6.1.2.1.1.5.0) (OctetString): TCC-TX
又例如我们可以通过SNMP命令来监控磁盘的空间大小,例子代码如下所示:

代码
private
void
button7_Click(
object
sender, EventArgs e)
{
double
[] diskstorage1, diskstorage2;
diskstorage1
=
snmpget(
"
127.0.0.1
"
,
"
public
"
,
1
);
this
.txtContent.Text
+=
Environment.NewLine;
diskstorage2
=
snmpget(
"
192.168.101.81
"
,
"
gci_RW
"
,
2
);
//
foreach (double dou in diskstorage1)
//
{
//
this.txtContent.Text += string.Format("{0} GB \r\n", dou.ToString("f2"));
//
}
}
double
[] snmpget(
string
ipaddress,
string
comname,
int
i)
{
double
cvolumn
=
0
, dvolumn
=
0
, cvolunmn1
=
0
, dvolumn1
=
0
, cvolumn2
=
0
, dvolumn2
=
0
;
double
[] backup
=
new
double
[
6
];
//
SNMP community name
OctetString community
=
new
OctetString(comname);
//
Define agent parameters class
AgentParameters param
=
new
AgentParameters(community);
//
Set SNMP version to 1 (or 2)
param.Version
=
(
int
)SnmpVersion.Ver1;
//
Construct the agent address object
//
IpAddress class is easy to use here because
//
it will try to resolve constructor parameter if it doesn't
//
parse to an IP address
IpAddress agent
=
new
IpAddress(ipaddress);
//
Construct target
UdpTarget target
=
new
UdpTarget((IPAddress)agent,
161
,
2000
,
2
);
//
Pdu class used for all requests
Pdu pdu
=
new
Pdu(PduType.Get);
//
区分两台服务器的硬盘mib代码
if
(i
==
2
)
{
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.5.2
"
);
//
硬盘C盘簇数
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.5.3
"
);
//
硬盘D盘簇数
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.6.2
"
);
//
硬盘C盘已用簇数
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.6.3
"
);
//
硬盘D盘已用簇数
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.4.2
"
);
//
硬盘C盘分配单元
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.4.3
"
);
//
硬盘D盘分配单元
}
else
if
(i
==
1
)
{
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.5.1
"
);
//
硬盘C盘簇数
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.5.2
"
);
//
硬盘D盘簇数
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.6.1
"
);
//
硬盘C盘已用簇数
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.6.2
"
);
//
硬盘D盘已用簇数
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.4.1
"
);
//
硬盘C盘分配单元
pdu.VbList.Add(
"
1.3.6.1.2.1.25.2.3.1.4.2
"
);
//
硬盘D盘分配单元
}
SnmpV1Packet result
=
new
SnmpV1Packet();
//
Make SNMP request
result
=
(SnmpV1Packet)target.Request(pdu, param);
//
If result is null then agent didn't reply or we couldn't parse the reply.
if
(result
!=
null
)
{
//
ErrorStatus other then 0 is an error returned by
//
the Agent - see SnmpConstants for error definitions
if
(result.Pdu.ErrorStatus
!=
0
)
{
//
agent reported an error with the request
this
.txtContent.Text
+=
string
.Format(
"
Error in SNMP reply. Error {0} index {1} \r\n
"
,
result.Pdu.ErrorStatus,
result.Pdu.ErrorIndex);
}
else
{
//
Reply variables are returned in the same order as they were added
//
to the VbList
int
a
=
int
.Parse(result.Pdu.VbList[
0
].Value.ToString());
int
b
=
int
.Parse(result.Pdu.VbList[
1
].Value.ToString());
int
c
=
int
.Parse(result.Pdu.VbList[
2
].Value.ToString());
int
d
=
int
.Parse(result.Pdu.VbList[
3
].Value.ToString());
int
num1
=
int
.Parse(result.Pdu.VbList[
4
].Value.ToString());
int
num2
=
int
.Parse(result.Pdu.VbList[
5
].Value.ToString());
cvolumn
=
(
double
)a
*
num1
/
1024
/
1024
/
1024
;
dvolumn
=
(
double
)b
*
num2
/
1024
/
1024
/
1024
;
cvolunmn1
=
(
double
)c
*
num1
/
1024
/
1024
/
1024
;
dvolumn1
=
(
double
)d
*
num2
/
1024
/
1024
/
1024
;
cvolumn2
=
cvolumn
-
cvolunmn1;
dvolumn2
=
dvolumn
-
dvolumn1;
backup[
0
]
=
cvolumn;
backup[
1
]
=
dvolumn;
backup[
2
]
=
cvolunmn1;
backup[
3
]
=
dvolumn1;
backup[
4
]
=
cvolumn2;
backup[
5
]
=
dvolumn2;
this
.txtContent.Text
+=
string
.Format(
"
c盘空间{0} GB \r\n
"
, cvolumn.ToString(
"
f2
"
));
this
.txtContent.Text
+=
string
.Format(
"
d盘空间{0} GB \r\n
"
, dvolumn.ToString(
"
f2
"
));
this
.txtContent.Text
+=
string
.Format(
"
c盘已用空间{0} GB \r\n
"
, cvolunmn1.ToString(
"
f2
"
));
this
.txtContent.Text
+=
string
.Format(
"
d盘已用空间{0} GB \r\n
"
, dvolumn1.ToString(
"
f2
"
));
this
.txtContent.Text
+=
string
.Format(
"
c盘剩余空间{0} GB \r\n
"
, cvolumn2.ToString(
"
f2
"
));
this
.txtContent.Text
+=
string
.Format(
"
d盘剩余空间{0} GB \r\n
"
, dvolumn2.ToString(
"
f2
"
));
}
}
else
{
this
.txtContent.Text
+=
string
.Format(
"
No response received from SNMP agent. \r\n
"
);
}
target.Close();
return
backup;
}
出来的结果就是显示各计算机的磁盘信息,如下所示:
66
GB
d盘空间73.
25
GB
c盘已用空间36.
61
GB
d盘已用空间31.
00
GB
c盘剩余空间61.
05
GB
d盘剩余空间42.
25
GB
c盘空间48.
83
GB
d盘空间57.
19
GB
c盘已用空间1.
70
GB
d盘已用空间6.
68
GB
c盘剩余空间47.
13
GB
d盘剩余空间50.
51
GB
另外利用SNMP可以发送约定的Trap协议到指定的计算机上,从而实现两个计算机上的交互操作,Trap协议可以发送多种数据类型,如字符类型、整形、日期类型、OID类型等信息,发送Trap协议比较简单,如下所示:
int
i
=
0
;
private
void
button8_Click(
object
sender, EventArgs e)
{
TrapAgent agent
=
new
TrapAgent();
VbCollection col
=
new
VbCollection();
//
连接状态 设备连接状态(0:通信正常 1:通信故障)
//
工作温度
//
告警描述
string
desc
=
string
.Format(
"
测试Trap内容
"
);
col.Add(
new
Oid(
"
.1.3.6.1.4.1.22014.99.2.1.6.2.1.1.1
"
),
new
Integer32(
0
));
col.Add(
new
Oid(
"
.1.3.6.1.4.1.22014.99.2.1.6.2.1.1.2
"
),
new
Integer32(
30
));
col.Add(
new
Oid(
"
.1.3.6.1.4.1.22014.99.2.1.6.2.4.1.1
"
),
new
OctetString(Encoding.Default.GetBytes(desc)));
//
Send the trap to the localhost port 162
string
hostIp
=
"
127.0.0.1
"
;
string
community
=
"
public
"
;
agent.SendV2Trap(
new
IpAddress(hostIp),
162
, community,
13433
,
new
Oid(
"
.1.3.6.1.6.3.1.1.5
"
), col);
i
++
;
}
通过接受数据的控制台,我们能可以查看到Trap协议接受到的情况,如下所示:
由于SNMP方面的应用应该很少人涉及到,因此对多数人来说,还是比较神秘的东西,本文抛砖引玉,希望与大家一起讨论学习。