想实现功能:作一个企业局域网网络设备管理的软件。
比如通过交换机的管理IP,无需telnet登录,也无需登录密码,直接查看交换机状态。网上找了很多资料,大多推荐使用snmp协议,C#开发可使用SnmpSharpNet组件来做。
但仍然无从下手。
网上搜索的代码如下,主要是通过已知的交换机管理IP和交换机的OID来查询实现,但大多数时候交换机的OID信息是未知的:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Net;
using SnmpSharpNet;namespace 交换机snmp.ClassFile
{
    /// <summary>
    /// 通过snmp获取交换机信息(需指定OID)
    /// </summary>
    class SnmpWork
    {
        public SnmpWork()
        {
            //   
            //TODO: 在此处添加构造函数逻辑   
            //   
        }        #region 通过oid字符数组获得相应的值
        public static Dictionary<string, string> getOIDValue(string host, string[] oid)
        {
            //返回变量   
            Dictionary<string, string> dic = new Dictionary<string, string>();            // SNMP community name   
            OctetString community = new OctetString("public");            // Define agent parameters class   
            AgentParameters param = new AgentParameters(community);
            // Set SNMP version to 1 (or 2)   
            param.Version = 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(host);            // Construct target   
            UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 1);            // Pdu class used for all requests   
            Pdu pdu = new Pdu(PduType.Get);            foreach (string singleoid in oid)
            {
                pdu.VbList.Add(singleoid);
            }            // Make SNMP request   
            SnmpV1Packet 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)
                {
                    for (int i = 0; i < result.Pdu.VbList.Count; i++)
                    {
                        dic.Add(result.Pdu.VbList[i].Oid.ToString(), result.Pdu.VbList[i].Value.ToString());
                    }
                    // Reply variables are returned in the same order as they were added   
                    //  to the VbList   
                }
            }
            target.Close();
            return dic;
        }
        #endregion        #region 通过snmpwalk返回oid根下面的所有值
        public static Dictionary<string, string> getWalkValue(string host, string irootOid)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            // SNMP community name   
            OctetString community = new OctetString("public");            // Define agent parameters class   
            AgentParameters param = new AgentParameters(community);
            // Set SNMP version to 2 (GET-BULK only works with SNMP ver 2 and 3)   
            param.Version = SnmpVersion.Ver2;
            // 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(host);            // Construct target   
            UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 1);            // Define Oid that is the root of the MIB   
            //  tree you wish to retrieve   
            Oid rootOid = new Oid(irootOid); // ifDescr               // This Oid represents last Oid returned by   
            //  the SNMP agent   
            Oid lastOid = (Oid)rootOid.Clone();            // Pdu class used for all requests   
            Pdu pdu = new Pdu(PduType.GetBulk);            // In this example, set NonRepeaters value to 0   
            pdu.NonRepeaters = 0;
            // MaxRepetitions tells the agent how many Oid/Value pairs to return   
            // in the response.   
            pdu.MaxRepetitions = 5;            // Loop through results   
            while (lastOid != null)
            {
                // When Pdu class is first constructed, RequestId is set to 0   
                // and during encoding id will be set to the random value   
                // for subsequent requests, id will be set to a value that   
                // needs to be incremented to have unique request ids for each   
                // packet   
                if (pdu.RequestId != 0)
                {
                    pdu.RequestId += 1;
                }
                // Clear Oids from the Pdu class.   
                pdu.VbList.Clear();
                // Initialize request PDU with the last retrieved Oid   
                pdu.VbList.Add(lastOid);
                // Make SNMP request   
                SnmpV2Packet result = (SnmpV2Packet)target.Request(pdu, param);
                // You should catch exceptions in the Request if using in real application.                   // 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)
                    {
                        // Walk through returned variable bindings   
                        foreach (Vb v in result.Pdu.VbList)
                        {
                            // Check that retrieved Oid is "child" of the root OID   
                            if (rootOid.IsRootOf(v.Oid))
                            {
                                dic.Add(v.Oid.ToString(), v.Value.ToString());
                            }
                            else
                            {
                                // we have reached the end of the requested   
                                // MIB tree. Set lastOid to null and exit loop   
                                lastOid = null;
                            }
                        }
                    }
                }
            }
            target.Close();
            return dic;
        }
        #endregion
    }
}
昨天在网上找了一个小软件,名字叫“getif”。
经过测试,输入交换机的管理IP,能把交换机的OID信息、端口状态(up或者down)、以及交换机中mac-address-table中的信息都读了出来。
不明白其原理,希望大家能介绍点经验。

解决方案 »

  1.   

    我试着调用public static Dictionary<string, string> getWalkValue(string host, string irootOid)代码为:
    Dictionary<string, string> dic_switch = ClassFiles.SnmpSwitchOid.getWalkValue(cbb_ip.Text.Trim(), ttx_oid.Text.Trim());
    在public static Dictionary<string, string> getWalkValue(string host, string irootOid)
    中,报错:“已添加了具有相同键的项”,说明Dictionary泛型值有重复的。
    看来网上给的这段代码还是有问题的。
    哎,竟没有一个回复啊。
    呵呵,无言郁闷中...
      

  2.   

    我在窗体Form1中,做了一个textbox,用于填写交换机IP,查询调用代码为:
    string[] Str_oid = { "1.3.6.1.2.1.1.1.0", "1.3.6.1.2.1.1.2.0", "1.3.6.1.2.1.1.3.0", "1.3.6.1.2.1.1.4.0", "1.3.6.1.2.1.1.5.0", "1.3.6.1.2.1.1.7.0" };
                        Dictionary<string, string> dic_switch = ClassFiles.SnmpSwitchOid.getOIDValue(cbb_ip.Text.Trim(), Str_oid);
    而这里的“getOIDValue”就是我上面贴的一个方法。
    现在已经可以通过这些OID得到交换机的SysDescr、sysObjectId、sysUpTime、sysContact、sysName、
    sysServices,但就是不知道获取交换机端口状态的oid是什么。
    网上查了一些,比如:1.3.6.1.2.1.2.2.1.8,调不出来
      

  3.   

    其实考虑做网络管理的话,这个功能的实现是很有价值的。
    将企业内用户IP等信息存在数据库,通过查看交换机的mac-address-table
    可以防止IP冲突
    随时浏览交换机状况
    都很有好处
    现在只从网上down了一个软件可以实现,但还是想自己做啊。
      

  4.   


    oid具体所代表的意思,就要你去查看MIB文件啦,里面有详细描述。建议:使用第三方软件先对你的交换机进行访问,分析后再在自己的程序里实现会好一些。  我用的第三方软件是SNMPc network manager有问题可以email我,尽量帮忙
      

  5.   

    试了N长时间,还是没有整出来,目前还是未果。
    尽管没有达到理想的效果,但还是谢谢rqx110,给了我很多启发。
    最近比较忙,如果能做出来,我会把代码在这里贴出来,希望对其他朋友有所帮助。
      

  6.   

    使用1.3.6.1.2.1.2.2.1.8.1以及以后的OID即可
      

  7.   

    我也发现SnmpSharpNet 已添加了具有相同键的项 这个问题,目前我只能暂时修改了组合字典那部分,从代码看来,字典第一个是key,第二个是value,key的内容就是oid,但是字典的key是不能重复的,所以一个oid有多个返回值的时候就会重复,你加个累加的就可以,可以解决重复的问题。
    以下是我修改后的代码。这是一个类,可以方便调用和修改
    using System;
    using System.Collections.Generic;
    //using System.Web;
    using System.Net;
    using SnmpSharpNet;
    /// <summary>
    ///SimpleSnmp 的摘要说明
    /// </summary>
    public class MySimpleSnmp
    {
    public MySimpleSnmp()
    {
    //
    //TODO: 在此处添加构造函数逻辑
    //
        }    #region 通过oid字符数组获得相应的值
        public static Dictionary<string,string> getOIDValue(string host, string[] oid) {
            //返回变量
            Dictionary<string, string> dic = new Dictionary<string, string>();        // SNMP community name
            OctetString community = new OctetString("public");        // Define agent parameters class
            AgentParameters param = new AgentParameters(community);
            // Set SNMP version to 1 (or 2)
            param.Version = 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(host);        // Construct target
            UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 1);        // Pdu class used for all requests
            Pdu pdu = new Pdu(PduType.Get);        foreach (string singleoid in oid) {
                pdu.VbList.Add(singleoid);
            }        // Make SNMP request
            SnmpV1Packet 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)
                {
                    for (int i = 0; i < result.Pdu.VbList.Count;i++ )
                    {
                        dic.Add(result.Pdu.VbList[i].Oid.ToString(), result.Pdu.VbList[i].Value.ToString());
                    }
                    // Reply variables are returned in the same order as they were added
                    //  to the VbList
                }
            }
            target.Close();
            return dic;
        }
        #endregion    #region 通过snmpwalk返回oid根下面的所有值
        public static Dictionary<string, string> getWalkValue(string host,string irootOid) {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            // SNMP community name
            OctetString community = new OctetString("public");        // Define agent parameters class
            AgentParameters param = new AgentParameters(community);
            // Set SNMP version to 2 (GET-BULK only works with SNMP ver 2 and 3)
            param.Version = SnmpVersion.Ver2;
            // 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(host);        // Construct target
            UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 5);        // Define Oid that is the root of the MIB
            //  tree you wish to retrieve
            Oid rootOid = new Oid(irootOid); // ifDescr        // This Oid represents last Oid returned by
            //  the SNMP agent
            Oid lastOid = (Oid)rootOid.Clone();        // Pdu class used for all requests
            Pdu pdu = new Pdu(PduType.GetBulk);        // In this example, set NonRepeaters value to 0
            pdu.NonRepeaters = 0;
            // MaxRepetitions tells the agent how many Oid/Value pairs to return
            // in the response.
            pdu.MaxRepetitions = 5;        int i = 1;//额外加个头
            // Loop through results
            while (lastOid != null)
            {
                // When Pdu class is first constructed, RequestId is set to 0
                // and during encoding id will be set to the random value
                // for subsequent requests, id will be set to a value that
                // needs to be incremented to have unique request ids for each
                // packet
                if (pdu.RequestId != 0)
                {
                    pdu.RequestId += 1;
                }
                // Clear Oids from the Pdu class.
                pdu.VbList.Clear();
                // Initialize request PDU with the last retrieved Oid
                pdu.VbList.Add(lastOid);
                // Make SNMP request
                SnmpV2Packet result = (SnmpV2Packet)target.Request(pdu, param);
                // You should catch exceptions in the Request if using in real application.            // 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)
                    {
                        // Walk through returned variable bindings                    
                        foreach (Vb v in result.Pdu.VbList)
                        {
                            // Check that retrieved Oid is "child" of the root OID
                            if (rootOid.IsRootOf(v.Oid))
                            {
                                //dic.Add(v.Oid.ToString(), v.Value.ToString());
                                dic.Add(i.ToString(), v.Value.ToString());
                                i += 1;
                            }
                            else
                            {
                                // we have reached the end of the requested
                                // MIB tree. Set lastOid to null and exit loop
                                lastOid = null;
                            }
                        }
                    }
                }
            }
            target.Close();
            return dic;
        }
        #endregion
    }目前还有个严重问题我还没解决,如果返回的值很多,就很容易超时或者过大什么的,我改了时间和重试次数都不行,请各位指教!
    谢谢!