当前位置: 代码迷 >> Android >> Android实现snmp协议(1)
  详细解决方案

Android实现snmp协议(1)

热度:28   发布时间:2016-04-28 02:21:34.0
Android实现snmp协议(一)
2015年一月初。接到华为一位老师的电话,让我帮忙做一款他们在北京展会上要用到的App,该App能够展示华为的网络设备运行状态并可以设置一些简单的参数,包括AP、LSW、AP、AR等。

华为老师跟我说他们是使用snmp协议v2c的版本进行管理的,这意味着我也得在Android设备实现该协议,并与他们的网络设备交互。

回去认真研究了一下并请教了一些对这块比较熟悉的小伙伴,总算对snmp有了一些粗浅的认识。

snmp是指简单网络设备管理协议,顾名思义就是对网络设备进行管理的通用标准协议,属于TCP/IP的应用层,snmp的服务器端占用的端口是161,客户端占用的是162(基于UDP协议)。

在windows上开启snmp协议可参照http://blog.csdn.net/zougangx/article/details/6977936。
需要注意的一点是:SNMP Service属性的安全选项卡中设置接受来自任何主机的snmp数据包,以便我们调试。


对已经建立了连接的两个设备之间,该协议使用了OID(对象标示符)作为查询的内容,OID的内容具体可参考http://www.cnblogs.com/aspx-net/p/3554044.html。OID有一部分是协议定义好的,有一部分设备厂商可以自己定义。

完成以上的步骤,并熟悉了基本的OID指令后,网上有写朋友说就可以使用Paessler SNMP Tester进行调试了,但是本人在实际操作中没有这么顺利,Paessler SNMP Tester一直显示noresponse,转而使用snmputil。(Paessler SNMP Tester和snmputil都是windows端测试snmp协议的工具,Paessler SNMP Tester具有图形化界面,snmputil没有,关于snmputil的操作可以参考http://blog.chinaunix.net/uid-21857285-id-3340217.html)

在使用snmputil的时候出现error on SnmpMgrRequest 40错误,参考以下网址得到解决:http://blog.csdn.net/wqjsir/article/details/8472006,在这篇文章中对陷阱选项卡进行了配置。至此,我的snmputil和Paessler SNMP Tester才正常的运行起来!

在计算机的服务列表中,可以看到:


其中Trap消息是需要手动去开启的,而service是自动开启。至于snmp trap服务怎么使用,snmp service的陷阱选项卡的设置原因我也不是很清楚,也希望有人知道的话不吝赐教,暂时不影响我做项目也没深入研究下去。

当两个服务都开启后,可以使用netstat -an|findstr "162"或netstat -an|findstr "161"查看端口是否开发,161开启之后就已经可以做本地测试了。



snmp协议是TCP/IP协议,是用c系语言完成的,本人以前移植过的uip1.0也是用c语言写的。而Android必须使用Java来实现,为此,本人首先使用了snmp4j这个jar包,建立了Java工程,仿造官方文档的示例,coding如下(需引入snmp4j的两个jar包):
class SnmpManager {     private TransportMapping transportMapping = null;     private Snmp snmp = null;     private int version;     public final static int version1 = SnmpConstants. version1;     public final static int version2c = SnmpConstants.version2c;     public final static int version3 = SnmpConstants. version3;     /**      * 构造方法      * @param version      */     public SnmpManager( int version) {            this. version = version;            try {                 // 设置成Udp协议                 transportMapping = new DefaultUdpTransportMapping();                 snmp = new Snmp( transportMapping);                 if (version == version3) {                      // 设置安全信息                     USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);                     SecurityModels. getInstance().addSecurityModel(usm);                }                 transportMapping.listen();           } catch (Exception e) {                e.printStackTrace();                System. out.println(e);           }     }     /**      * @param sync      * @param bro      * @param pdu      * @param addr      * 发送消息方法      */     public void sendMsg(boolean sync, final boolean bro, PDU pdu, String addr) {           Address targetAddres = GenericAddress. parse(addr);           Target target = null;            if ( this. version == version3) {                 snmp.getUSM().addUser( new OctetString( "MD5DES"), new UsmUser( new OctetString( "MD5DES"), AuthMD5. ID, new OctetString("MD5DESUserAuthPassword" ), PrivDES.ID, new OctetString("MD5DESUserPrivPassword" )));                target = new UserTarget();                 // 设置安全级别                target.setSecurityLevel(SecurityLevel. AUTH_PRIV);                target.setSecurityName( new OctetString("MD5DES"));                target.setVersion(SnmpConstants. version3);           } else {                target = new CommunityTarget();                 if ( this. version == version1) {                     target.setVersion( version1);                     ((CommunityTarget) target).setCommunity(new OctetString("public" ));                } else {                     target.setVersion( version2c);                     ((CommunityTarget) target).setCommunity(new OctetString("public" ));                }           }           target.setAddress(targetAddres);           target.setRetries(2);           target.setTimeout(1000);            if (sync) {                 // 发送报文 并且接受响应                ResponseEvent response = null;                 try {                     response = snmp.send(pdu, target);                } catch (IOException e) {                      // TODO Auto-generated catch block                     e.printStackTrace();                     System. out.println(e);                }                 // 处理响应                System. out.println( "Synchronize message from " + response.getPeerAddress() + "/nrequest:" + response.getRequest() + "/nresponse:" + response.getResponse());                           } else {                ResponseListener listener = new ResponseListener() {                      @Override                      public void onResponse(ResponseEvent event) {                            if (!bro) {                                ((Snmp) event.getSource()).cancel(event.getRequest(), this );                           }                            // 处理响应                           PDU request = event.getRequest();                           PDU response = event.getResponse();                           System. out.println( "Asynchronise message from " + event.getPeerAddress() + "/nrequest:" + request + "/nresponse:" + response);                     }                };                 try {                      snmp.send(pdu, target, null, listener);                } catch (IOException e) {                     e.printStackTrace();                     System. out.println(e);                }           }     }}public class SnmpTest {     public static String myVersion = "";     static boolean sync = false;     static boolean bro = false;     /**      * 主函数      * @param args      */     public static void main(String[] args) {           SnmpManager manager = new SnmpManager(SnmpConstants.version2c );            // 构造报文           PDU pdu = new PDU();            // PDU pdu = new ScopedPDU(); version3使用            // 设置要获取的对象ID           OID oids = new OID( "1.3.6.1.2.1.1.1.0");//         OID oids = new OID(new int [] { 1, 3, 6, 1, 2, 1, 1, 1, 0 });           pdu.add( new VariableBinding(oids));            // 设置报文类型           pdu.setType(PDU. GET);//         ((ScopedPDU) pdu).setContextName(new OctetString("priv"));             // 发送消息 其中最后一个是想要发送的目标地址           manager.sendMsg( true, true, pdu, "udp:127.0.0.1/161");                }}

运行结果如下:


等我把这段Java代码移植到Android工程中时,却不起作用了。我百度、google、stackoverflow等一些网站都看过了,在stackoverflow上有位朋友也是遇到和我一样的问题,有人回复snmp4j无法在Android上无法使用,究竟为什么,本人也不能解释给大家听,需要更厉害的人了!

因为是华为老师的项目,我不能这样尥蹶子,就继续查找相关资料,我想应该有人做出了类似snmp4j的Android版本吧,功夫不负有心人。
https://www.webnms.com/snmpapi-android/index.html
这个网站的闭源包提供了这个功能,做snmp的开发者,不妨研读一下,我就是在使用了此网站的开发包,完成了snmp的协议。


private void buttonFun() {		noNull();				new Thread(new Runnable() {			@Override			public void run() {				// TODO Auto-generated method stub				api = new SnmpAPI();				session = new SnmpSession(api);				SnmpPDU pdu = new SnmpPDU();				UDPProtocolOptions protocol = new UDPProtocolOptions();				protocol.setRemoteHost(getText(target));				protocol.setRemotePort(Integer.parseInt(getText(port)));				pdu.setProtocolOptions(protocol);				// Build Get request PDU				pdu.setCommand(SnmpAPI.GET_REQ_MSG);			    pdu.setCommunity(getText(community));			    			    if(version.getSelectedItemPosition()==0){			    	pdu.setVersion(SnmpAPI.SNMP_VERSION_1);				    				    }else if(version.getSelectedItemPosition()==1){			    	pdu.setVersion(SnmpAPI.SNMP_VERSION_2C);			    				    }else if(version.getSelectedItemPosition()==2){			    	//还需设置MD5 SHA认证密码等			    	pdu.setVersion(SnmpAPI.SNMP_VERSION_3);			    }			    				pdu.setTimeout(Integer.parseInt(getText(timeout)));				pdu.setRetries(Integer.parseInt(getText(retries)));				// SnmpOID oid = new SnmpOID("1.3.6.1.2.1.1.1.0");				// SnmpOID oid = new SnmpOID((SnmpOID)(getText(oid)));				// pdu.addNull(oid);								String oidstr = getText(oid);				String str[] = oidstr.split("\\.");				int a[] = new int[9];				for(int i=0; i<str.length; i++){					a[i] = Integer.parseInt(str[i]);				}				//				int a[] = { 1, 3, 6, 1, 2, 1, 1, 1, 0 };				SnmpOID oid = new SnmpOID(a);				pdu.addNull(oid);				SnmpPDU resp = null;				try {					session.open();					resp = session.syncSend(pdu);				} catch (SnmpException e) {					// TODO Auto-generated catch block					e.printStackTrace();					System.out.println(e);				}				if (resp != null) {					// return varBinds string					UDPProtocolOptions options = (UDPProtocolOptions) resp.getProtocolOptions();					String resultString = "Response PDU received from " + options.getRemoteAddress() + ".\n"; // No I18N					resultString = resultString + "Community = " + resp.getCommunity() + ".\n\n"; // No I18N					if (resp.getErrstat() == 0) {						resultString = resultString + "VARBINDS :\n\n"; // No I18N						resultString = resultString + resp.printVarBinds();					} else {						// Check for error in response						resultString = resultString + resp.getError();					}										Message msg = new Message();					msg.what = 1000;					msg.obj = resultString;					myHandler.sendMessage(msg);										if(session != null) {			            session.close();			    	}			    	if(api != null) {			    		api.close();			    	}				} else {					String errorString = "Request timed out to: " + getText(target); // No I18N					Message msg = new Message();					msg.what = 1000;					msg.obj = errorString;					myHandler.sendMessage(msg);										if(session != null) {			            session.close();			    	}			    	if(api != null) {			    		api.close();			    	}				}			}		}).start();	}
做到这份上,跟华为的老师联系上了,他们跟我说年前比较忙,拖到年后才能详谈需求业务,我也暂时搁置此项目,去做别的事了。也许有新的情况,我会写个第二篇,希望对大家有帮助。



  相关解决方案