由于项目的需要,需要使用SNMP来进行相关的开发,需要在我的程序中利用SNMP的Trap协议给指定的系统程序发送相关的设备数据信息, 使得其系统能够监控到设备的最新信息以及状态,对方只是提供了一个Java的例子,而我的程序是C#开发的,因此对这方面的知识进行了解学习,完成了相关的功能,本文有感于此,对SNMP方面做了一些开发总结,以求树碑到此一游,独乐不如众乐,邀兴趣之士猎奇探秘.

首先介绍标题的几个问题,SNMP是什么,snmpsharpnet又是什么,开发能解决什么问题?

SNMP是什么呢?

简单来说,SNMP主要就是一种特定的网络管理协议,用来获取设备相关信息的一种一些,复杂来讲,就很讲究了,我不在长篇大量介绍重复的内容,需要了解可以参考下面几篇博文:

SNMP介紹及命令

SNMP基础简介

snmpsharpnet又是什么呢?

snmpsharpnet是基于C#开发一个开源组件,主要是为了方便使用SNMP协议而生,支持各种SNMP各种版本、各种指令的一个优秀组件。其官方网站是:
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();
}

运行后可以显示指定机器的基本信息,如下所示:

sysDescr(1.3.6.1.2.1.1.1.0) (OctetString): Hardware: x86 Family 6 Model 26 Stepping 5 AT/AT COMPATIBLE - Software: Windows Version 5.2 (Build 3790 Multiprocessor Free)
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;
}

出来的结果就是显示各计算机的磁盘信息,如下所示:

c盘空间97.
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方面的应用应该很少人涉及到,因此对多数人来说,还是比较神秘的东西,本文抛砖引玉,希望与大家一起讨论学习。

标签: none

添加新评论