使用snmp4j通過snmpv3協議獲取指標

參考:https://blog.csdn.net/zhouzhiwengang/article/details/46816371,本文對此又做了精進

先說一下參考鏈接中沒提到的點:

1、通過snmp.getUSM()獲取到的USM實例是同一個,因此不要在多線程併發中去往USM中添加用戶或修改,否則有時會報找不到securityName的異常,在stackoverflow上有相關問題

2、USM有三種添加用戶的方法,其中通過engineID的方式添加的時候,再獲取時候也要通過engineID+name去獲取,在參考中體現在,設置target的時候要設置AuthoritativeEngineID,否則在執行時查詢USM會報找不到securityName

//加上這句
target.setAuthoritativeEngineID(new OctetString("0002651100").getValue());

更新:此engineID爲設備側所配置的engineID,非snmp4j所特有的,在敲snmpwalk命令時也發現此參數

 

下面是我自己測試時用到代碼段,可以修改調試一下,加深理解:

package com.moon.test3;

import java.io.IOException;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.TimeUnit;

import org.snmp4j.PDU;
import org.snmp4j.ScopedPDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.UserTarget;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.AuthMD5;
import org.snmp4j.security.PrivDES;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.security.UsmUser;
import org.snmp4j.security.UsmUserEntry;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import org.snmp4j.util.DefaultPDUFactory;
import org.snmp4j.util.TableEvent;
import org.snmp4j.util.TableUtils;
 
public class SNMP {
	public static void main(String[] args) throws IOException, InterruptedException {
		
		Snmp snmp = new Snmp(new DefaultUdpTransportMapping());
		USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
		SecurityModels.getInstance().addSecurityModel(usm);
		snmp.listen();
		
		// Add User
		Thread thread1 = new Thread( new Runnable() {
			@Override
			public void run() {
				try {
					TimeUnit.SECONDS.sleep(1);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				UsmUser user = new UsmUser(
						new OctetString("qiucf"),
						AuthMD5.ID, new OctetString("qiucfsnmpv3pwd"),
						PrivDES.ID, new OctetString("qiucfsnmpv3k"));
				//If the specified SNMP engine id is specified, this user can only be used with the specified engine ID
				//So if it's not correct, will get an error that can't find a user from the user table.
				//snmp.getUSM().addUser(new OctetString("nmsAdmin"), new OctetString("0002651100"), user);
				snmp.getUSM().addUser(user);
				
				UsmUser user2 = new UsmUser(
						new OctetString("qiucf2"),
						AuthMD5.ID, new OctetString("qiucfsnmpv3pwd2"),
						PrivDES.ID, new OctetString("qiucfsnmpv3k2"));
				//這種方式添加的用戶僅能通過name和engineID獲取,不能單純通過name獲取
				snmp.getUSM().addUser(new OctetString("qiucf2"), new OctetString("0002651100"), user2);
			}
		});
		thread1.start();
		
		Thread thread2 = new Thread(new Runnable() {
			@Override
			public void run() {
				
				try {
					TimeUnit.SECONDS.sleep(2);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				Snmp snmp2;
				UsmUserEntry entry = null;
				try {
					snmp2 = new Snmp(new DefaultUdpTransportMapping());
					//entry = snmp2.getUSM().getUserTable().getUser(new OctetString("0002651100"), new OctetString("qiucf2"));
					entry = snmp2.getUSM().getUserTable().getUser(new OctetString("0002651100"),new OctetString("qiucf2"));
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				
				try {
					System.out.println(entry.getUserName());
				} catch (Exception e) {
					System.out.println("No such user");
				}
			}
		});
		thread2.start();
		
		try {
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		UserTarget target = new UserTarget();
		target.setVersion(SnmpConstants.version3);
		target.setAddress(new UdpAddress("192.168.0.100/161"));
		target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
		target.setSecurityName(new OctetString("qiucf2"));
		//加上這句
		target.setAuthoritativeEngineID(new OctetString("0002651100").getValue());
		
		target.setTimeout(3000);	//3s
		target.setRetries(0);
				
		OctetString contextEngineId = new OctetString("0002651100[02]");
		sendRequest(snmp, createGetPdu(contextEngineId), target);
		snmpWalk(snmp, target, contextEngineId);
	}
	
	private static PDU createGetPdu(OctetString contextEngineId) {
		ScopedPDU pdu = new ScopedPDU();
		pdu.setType(PDU.GET);
		pdu.setContextEngineID(contextEngineId);	//if not set, will be SNMP engine id
		//pdu.setContextName(contextName);  //must be same as SNMP agent
		
		pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.3.0")));	//sysUpTime
		pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5.0")));	//sysName
		pdu.add(new VariableBinding(new OID("1.3.6.1.2.1.1.5")));	//expect an no_such_instance error
		return pdu;
	}
	
	private static void sendRequest(Snmp snmp, PDU pdu, UserTarget target)
	throws IOException {
		ResponseEvent responseEvent = snmp.send(pdu, target);
		PDU response = responseEvent.getResponse();
		
		if (response == null) {
			System.out.println("TimeOut...");
		} else {
			if (response.getErrorStatus() == PDU.noError) {
				Vector<? extends VariableBinding> vbs = response.getVariableBindings();
				for (VariableBinding vb : vbs) {
					System.out.println(vb + " ," + vb.getVariable().getSyntaxString());
				}
			} else {
				System.out.println("Error:" + response.getErrorStatusText());
			}
		}
	}
	
	private static void snmpWalk(Snmp snmp, UserTarget target, OctetString contextEngineId) {
		TableUtils utils = new TableUtils(snmp,
				new MyDefaultPDUFactory(PDU.GETNEXT, //GETNEXT or GETBULK)
										contextEngineId));
		utils.setMaxNumRowsPerPDU(5);	//only for GETBULK, set max-repetitions, default is 10
		OID[] columnOids = new OID[] {
				new OID("1.3.6.1.2.1.1.9.1.2"),	//sysORID
				new OID("1.3.6.1.2.1.1.9.1.3")	//sysORDescr
		};
		// If not null, all returned rows have an index in a range (lowerBoundIndex, upperBoundIndex]
		List<TableEvent> l = utils.getTable(target, columnOids, new OID("3"), new OID("10"));
		for (TableEvent e : l) {
			System.out.println(e);
		}
	}
	
	private static class MyDefaultPDUFactory extends DefaultPDUFactory {
		private OctetString contextEngineId = null;
		
		public MyDefaultPDUFactory(int pduType, OctetString contextEngineId) {
			super(pduType);
			this.contextEngineId = contextEngineId;
		}
 
		@Override
		public PDU createPDU(Target target) {
			PDU pdu = super.createPDU(target);
			if (target.getVersion() == SnmpConstants.version3) {
				((ScopedPDU)pdu).setContextEngineID(contextEngineId);
			}
			return pdu;
		}		
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章