利用C#开发基于snmpsharpnet基础的SNMP开发应用

简介:

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

本文转自博客园伍华聪的博客,原文链接:利用C#开发基于snmpsharpnet基础的SNMP开发应用,如需转载请自行联系原博主。




目录
相关文章
|
9天前
|
开发框架 前端开发 JavaScript
采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示
技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
5月前
|
缓存 开发框架 监控
一个C#开发的开源的快速启动工具
一个C#开发的开源的快速启动工具
43 0
|
1月前
|
数据挖掘 C# 开发工具
采用C#语言开发的全套医院体检系统PEIS源码功能介绍
体检系统,是专为体检中心/医院体检科等体检机构,专门开发的全流程管理系统,通过软件实现检测仪器数据自动提取,内置多级医生工作台,细化工作将体检检查结果汇总,生成体检报告登记到计算机系统中。通过软件系统进行数据分析统计与评判以及建立体检相关的体检档案。从而实现体检流程的信息化,提高工作效率,减少手动结果录入的一些常犯错误。 在实际应用中,医院体检系统能够解决传统体检中手工操作带来的问题,如工作量大、效率低下、易漏检、重检或错检等。通过与医院信息系统(如HIS、LIS、PACS等)的连接,系统能够满足体检中心的日常工作流程,提供更好的管理、统计和查询分析功能。同时,基于网络基础的系统可以在网上传输
24 1
|
3月前
|
存储 C#
C#入门开发(Hello World,运算符)
C#入门开发(Hello World,运算符)
27 0
|
4月前
|
JavaScript C#
【傻瓜级JS-DLL-WINCC-PLC交互】2.wincc使用C#开发的.net控件
【傻瓜级JS-DLL-WINCC-PLC交互】2.wincc使用C#开发的.net控件
41 0
|
4月前
|
SQL 关系型数据库 MySQL
C#程序设计案例开发教程
C#程序设计案例开发教程
48 0
|
4月前
|
网络协议 C# C++
BytesIO | C# 超简洁的TCP服务端开发(完整源码+视频教程)
本章将继续利用BytesIO开发TCP的服务端,简洁明了依然是主旋律,我们要在三十行代码内除了实现一个TCP服务端以外,使其支持聊天室(消息转发)、连接数限制、心跳超时检测等功能。 现在,一起跟着视频敲一敲吧!
166 0
BytesIO | C# 超简洁的TCP服务端开发(完整源码+视频教程)
|
4月前
|
存储 算法 数据处理
C# | 上位机开发新手指南(十一)压缩算法
流式压缩 流式压缩是一种能够实时处理数据流的压缩方式,例如音频、视频等实时传输的数据。 通过流式压缩算法,我们可以边读取边压缩数据,并能够随时输出已压缩的数据,以确保数据的实时性和减少存储和传输所需的带宽。 块压缩 块压缩则是将数据划分为固定大小的块,在每个块内进行独立的压缩处理。块压缩通常适用于文件、存储、传输等离线数据处理场景。 字典压缩 字典压缩是一种基于字典的压缩算法,通过建立一个字典来存储一组重复出现的字符串,并将这些字符串替换成字典中相应的索引,从而减少数据的存储和传输。字典压缩算法可以更好地处理数据中的重复模式,因为它们可以通过建立字典来存储和恢复重复出现的字符串。
46 0
C# | 上位机开发新手指南(十一)压缩算法
|
4月前
|
算法 C# 数据安全/隐私保护
C# | 上位机开发新手指南(十)加密算法——ECC
本篇文章我们将继续探讨另一种非对称加密算法——ECC。 严格的说,其实ECC并不是一种非对称加密算法,它是一种基于椭圆曲线的加密算法,广泛用于数字签名和密钥协商。 与传统的非对称加密算法(例如RSA)不同,ECC算法使用椭圆曲线上的点乘法来生成密钥对和进行加密操作,而不是使用大数分解等数学算法。这使得ECC算法具有相同的安全性和强度,但使用更少的位数,因此在资源受限的环境中具有优势。 ECC算法虽然使用公钥和私钥进行加密和解密操作,但是这些操作是基于点乘法实现的,而不是基于大数分解等算法实现的。因此,ECC算法可以被视为一种非对称加密算法的变体,但是它与传统的非对称加密算法有所不同。
130 0
C# | 上位机开发新手指南(十)加密算法——ECC
|
4月前
|
XML 算法 安全
C# | 上位机开发新手指南(九)加密算法——RSA
RSA的特性 非对称性 RSA算法使用公钥和私钥两个不同的密钥,公钥用于加密数据,私钥用于解密数据。公钥可以公开,任何人都可以使用,而私钥只有密钥持有人可以访问。 安全性 RSA算法基于大数分解难题,即将一个大的合数分解成其质数因子的乘积。由于目前没有有效的算法可以在合理的时间内对大质数进行分解,因此RSA算法被认为是一种安全的加密算法。 可逆性 RSA算法既可以用于加密,也可以用于解密。加密和解密都是可逆的过程,只要使用正确的密钥,就可以还原原始数据。 签名 RSA算法可以用于数字签名,用于验证数据的完整性和真实性。签名过程是将数据使用私钥进行加密,验证过程是将签名使用公钥进行解密。
102 0
C# | 上位机开发新手指南(九)加密算法——RSA