Java Dynamic Management Kit 5.0 Tutorial

Synchronous Managers

The synchronous SNMP manager is the simplest to program: the manager sends a request to an agent (peer) and waits for the answer. During the wait, the manager is blocked until either a response is received or the timeout period expires.

The SNMP manager API allows two ways of referring to variables when issuing requests:

Referring directly to OIDs requires no configuration but makes code less flexible. The advantages of using variable names are simplified coding and the independence of manager code when custom MIBs are modified. The SNMP manager API supports variable names by storing a description of the MIB it accesses in the SnmpOid object.

To refer to variable names, the manager needs to initialize this description with an OID table object. The OID table is instantiated from a subclass of the SnmpOidTableSupport class generated by the mibgen tool when compiling the MIB. Because this support class is regenerated whenever the MIB is recompiled, the new MIB definition is automatically loaded into the manager when it is started (see the Example 19–1).

The SNMP manager API specifies the SnmpPeer object for describing an agent, and the SnmpParameters object for describing its read-write communities and its protocol version (SNMPv1 or SNMPv2). The objects SnmpUsmPeer and SnmpUsmParameters perform these roles under SNMPv3, and handle user-based security parameters. The SnmpSession is an object for sending requests. The session instance has an SnmpOptions field that we can use to set multiplexing and error fixing behavior.


Note –

The objects specified by the SNMP manager API are not MBeans and cannot be registered in an MBean server to create a manager that can be controlled remotely. However, you can write an MBean that uses these classes to retrieve and expose information from SNMP agents.


A manager can contain any number of peers, one for each agent it accesses, and any number of sessions, one for each type of behavior it implements. Once the peers and the sessions are initialized, the manager can build lists of variables and send session requests to operate on them. The session returns a request object, and the manager calls its waitForCompletion method with the desired timeout delay.

Finally, the manager analyzes the result of the request, first to see if there were any errors, then to extract the data returned by the request.

Synchronous SNMPv1 and SNMPv2 Managers

Example 19–1 shows the code of the main method of the SyncManager application for SNMPv1 and SNMPv2. It applies all the steps described in the previous section to execute a very simple management operation.


Example 19–1 SNMPv1 and SNMPv2 SyncManager Example

The SyncManager example is found in the examplesDir/Snmp/Manager directory.

// read the command line parameters
String host = argv[0];
String port = argv[1];

// Specify the OidTable containing all the MIB II knowledge
// Use the OidTable generated by mibgen when compiling MIB II
//
SnmpOidTableSupport oidTable = new RFC1213_MIBOidTable();
SnmpOid.setSnmpOidTable(oidTable);
       
SnmpPeer agent = new SnmpPeer(host, Integer.parseInt(port));
     
// When creating the parameter object, you can specify the
// read and write community to be used when querying the agent.
SnmpParameters params = new SnmpParameters("public", "private");
agent.setSnmpParam(params);

SnmpSession session = new SnmpSession("SyncManager session");

// When invoking a service provided by the SnmpSession, it
// will use the default peer if none is specified explicitly
session.setDefaultPeer(agent);

// Create a listener and dispatcher for SNMP traps:
// SnmpEventReportDispatcher will run as a thread and
// listens for traps in UDP port = agent port + 1
SnmpEventReportDispatcher trapAgent =
    new SnmpEventReportDispatcher(Integer.parseInt(port)+1);
// TrapListenerImpl will receive a callback
// when a valid trap PDU is received.
trapAgent.addTrapListener(new TrapListenerImpl()); 
new Thread(trapAgent).start();

// Build the list of variables you want to query.
// For debugging, you can associate a name to your list.
SnmpVarbindList list= new SnmpVarbindList(
    "SyncManager varbind list");
     
// We want to read the "sysDescr" variable.
list.addVariable("sysDescr.0");
    
// Make the SNMP get request and wait for the result.
SnmpRequest request = session.snmpGet(null, list);
boolean completed = request.waitForCompletion(10000);

// Check for a timeout of the request.
if (completed == false) {
    java.lang.System.out.println(
"Request timed out. Check if agent can be reached");
    java.lang.System.exit(0);
}

// Check if the response contains an error.
int errorStatus = request.getErrorStatus();
if (errorStatus != SnmpDefinitions.snmpRspNoError) {
    java.lang.System.out.println("Error status = " + 
        SnmpRequest.snmpErrorToString(errorStatus));
    java.lang.System.out.println("Error index = " +
        request.getErrorIndex());
    java.lang.System.exit(0);
}

// Now we can extract the content of the result.
SnmpVarbindList result = request.getResponseVbList();
java.lang.System.out.println("Result: \n" + result);

[...] // Wait for user to type enter. Traps will be handled.

// End the session properly and we're done
session.destroySession();
java.lang.System.exit(0);

In this SNMP manager application, we demonstrate how to implement and enable a trap listener for the traps sent by the agent. First we need to instantiate an SnmpEventReportDispatcher object. Then we add our listener implementation through its addTrapListener method, and finally we start its thread. Trap listeners can be implemented in any manager using the SNMP manager API, not only synchronous managers.

Configuring SNMPv3 Security for Managers

Before you run the SNMPv3 manager examples, you require some information about how SNMPv3 user-based model (USM) security is configured. Below is a brief description of the SNMPv3 security mechanism that provides you with the information you need to run the SNMPv3 examples in this chapter. Full descriptions of the SNMPv3 security mechanisms are given in SNMPv3 User-Based Security Model.

An SNMPv3 manager requires a security file, in the same way as an SNMPv3 agent does. The jdmk.security file for an SNMPv3 manager differs slightly from that of an SNMPv3 agent, as shown in the following example.


Example 19–2 A jdmk.security File for an SNMPv3 Manager

#Authentication only.
userEntry=0x8000002a05819dcb6e00001f95,defaultUser,,
usmHMACMD5AuthProtocol,mypasswd

# #####APPENDED PROPERTY####
localEngineBoots=5

# #####APPENDED PROPERTY####
localEngineID=0x8000002a05000000ec4c49ded9

In a manager's security file, there is more emphasis on the engine ID than in an agent's security file. The userEntry provides all the security information the manager needs to communicate with a particular authoritative agent, as follows:

0x8000002a05819dcb6e00001f95

This is the engine ID of the agent with which the manager will communicate

defaultUser

The authorized user for that agent

usmHMACMD5AuthProtocol

The authentication algorithm; in this case, HMAC MD5

mypasswd

The privacy password

In this example, the information in the userEntry corresponds to the security information provided in the AgentV3 example's jdmk.security file, in Example 18–3. Therefore, this manager can communicate with that agent.

The remaining information pertains to the manager itself:

localEngineBoots

Sets how many times the local engine will boot

localEngineID

Represents the ID of the engine associated to the SNMP session in which the manager is running

Synchronous SNMPv3 Managers

The example synchronous manager application created for SNMPv3 is similar to the SNMPv1/v2 manager, except that it implements SNMPv3 user-based USM mechanisms before making requests.


Example 19–3 SNMPv3 SyncManagerV3 Example

The SyncManagerV3 example is in the examplesDir/Snmp/Manager directory.

			//Read the command line parameters
        final String host = argv[0];
        final String port = argv[1];

        // Initialize trace property. 
        [...]
  
        try {
            
     		 // Initialize the SNMP Manager API.
            final SnmpOidTableSupport oidTable = new RFC1213_MIBOidTable();
            SnmpOid.setSnmpOidTable(oidTable);
       
      		// Build the session.
            //
			    try {
						session= new SnmpSession("SyncManagerV3 session");
	   			 }catch(SnmpStatusException e) {
						println(e.getMessage());
						java.lang.System.exit(0);
	    		}
	    		catch(IllegalArgumentException e) {
				// If the engine configuration is faulty 
				println(e.getMessage());
				java.lang.System.exit(0);
	    		}
	
	    		// Access the SNMPv3 engine using getEngine
	    		//
	   			final SnmpEngine engine = session.getEngine();
	    
	    		// Create an SnmpUsmPeer object
 				//
			   final SnmpUsmPeer agent = 
				new SnmpUsmPeer(engine, host, Integer.parseInt(port));
	    
	    		// Create USM parameters
 				//
			   final SnmpUsmParameters p = 
				new SnmpUsmParameters(engine, "defaultUser");
	    
	    		// Set the security level 
				//
			 	p.setSecurityLevel(SnmpDefinitions.authNoPriv);

	    		// Contextualize the send request
	 		   //
	   			 p.setContextName("TEST-CONTEXT".getBytes());

	    		// Set the contextEngineId discovered by the peer upon 
				// creation
	   			 p.setContextEngineId(agent.getEngineId().getBytes());
	    
	    		// Associate the parameter with the agent.
	    		//
	    		agent.setParams(p);
	
	    
	    		// Discover time of creation and boot
			   //
			   agent.processUsmTimelinessDiscovery();
	    
	    		// Associate a default peer (agent) to an SnmpSession.
	    		// 
			   session.setDefaultPeer(agent);

	    		// Create a taskServer for processing traps (optional)
	    	    final DaemonTaskServer taskServer = new DaemonTaskServer();
	    		taskServer.start(Thread.NORM_PRIORITY);
	    
	    		// Create a listener and dispatcher for SNMP traps 
	    	   //
	    		final SnmpEventReportDispatcher trapAgent =
				new SnmpEventReportDispatcher(engine, 
					      Integer.parseInt(port) + 1, 
					      taskServer, null);
	    
	    		trapAgent.addTrapListener(new TrapListenerImpl());
           	final Thread trapThread = new Thread(trapAgent);
	    		trapThread.setPriority(Thread.MAX_PRIORITY);
			   	trapThread.start();	    
	    
	    		// Build the list of variables you want to query
	    	    //
	    		final SnmpVarBindList list = 
				new SnmpVarBindList("SyncManagerV3 varbind list");
	    
	    		// Read the "sysDescr" variable
			   //
           list.addVarBind("sysDescr.0");
	    
	    		// Make the SNMP get request and wait for the result
	    		//
	    		final SnmpRequest request = 
				session.snmpGetRequest(null, list);
	   			println("SyncManagerV3::main:" +
				    "Send get request to SNMP agent on " + host + 
				    " at port " + port);
			   final boolean completed = request.waitForCompletion(10000);
	    
	    		// Check for a timeout
	    		//
            if (completed == false) {
                println("SyncManagerV3::main:" + 
						" Request timed out. Check if agent  
						  can be reached");
		
                // Print request.
                //
                println("Request: " + request.toString());
                java.lang.System.exit(0);
            }
	    
            // Check the response for errors 
	    		//
            final int errorStatus = request.getErrorStatus();
            if (errorStatus != SnmpDefinitions.snmpRspNoError) {
                println("Error status = " + 
					 SnmpRequest.snmpErrorToString(errorStatus));
                println("Error index = " + 
					 request.getErrorIndex());
                java.lang.System.exit(0);
            }
       
            // Display the result.
            //
            final SnmpVarBindList result = request.getResponseVarBindList();
            println("Result: \n" + result);
       
            [...]

            // End the session
            //
            session.destroySession();
       
	    	    trapAgent.close();
	    		 taskServer.terminate();
            java.lang.System.exit(0);
     
				[...]
}

The first instantiated session creates an engine. This engine can be accessed using the getEngine method. To avoid excessive engine creation for each instantiated session, the first engine can be shared between SNMP session objects. Whilst sharing is possible, it should be avoided. It represents an unnecessary increase in overhead and limits the security possibilities because only one security file can be associated with an engine.

The engine is used by all the other classes in the application programming interface (API) to access the USM configuration, contained in the jdmk.security file associated with that session. In Example 19–3, when the peer p is created, it discovers its engineId, and then uses it as the SNMPv3 ContextEngineId. When the request is sent, this engine ID is included as a parameter by setContextEngineId.

In this example, the level of security is set as authentication without privacy. Consequently, this level of security is applied to all the requests between this manager and the peers associated with it, via the security parameters. This level of security must match the level specified in the engine's jdmk.security file.

It is also possible to access MIBs that have been registered in the scope of a context (see Binding the MIB MBeans for details of contextualized MIBs). In this example, the context TEST-CONTEXT is used, and is set as a parameter in the request by setContextName.

Finally, before sending any requests, if authentication is activated, the timeliness parameters of the request are discovered, using processUsmTimelinessDiscovery.

SNMP Trap Handler

A trap handler for the SNMP manager is an object that implements the SnmpTrapListener interface in the javax.management.snmp.manager package. When this object is bound as a listener of an SnmpEventReportDispatcher object, its methods are called to handle trap PDUs.

A trap listener is not a notification listener because the dispatcher is not a notification broadcaster. The listener has callback methods that work in the same manner, but they are given objects that represent traps, not instances of the Notification class.

The interface defines three methods, one for processing SNMPv1 traps, another for SNMPv2 traps and a third for SNMPv3 traps. Trap PDU packets have already been decoded by the dispatcher, and these methods handle an object representation of the trap: SnmpPduTrap objects for SNMPv1,SnmpPduRequest objects for SNMPv2 and SnmpScopedPduRequest for SNMPv3.


Example 19–4 SnmpTrapListener Implementation

public class TrapListenerImpl implements SnmpTrapListener {

		public void processSnmpTrapV1(SnmpPduTrap trap) {
        println("NOTE: TrapListenerImpl received trap :");
        println("\tGeneric " + trap.genericTrap);
        println("\tSpecific " + trap.specificTrap);
        println("\tTimeStamp " + trap.timeStamp);
        println("\tAgent adress " + trap.agentAddr.stringValue());
    }

    public void processSnmpTrapV2(SnmpPduRequest trap) {
        println("NOTE: Trap V2 not of interest !!!");
    }

    public void processSnmpTrapV3(SnmpScopedPduRequest trap) {
			println("NOTE: TrapListenerImpl received trap V3:");
			println("\tContextEngineId : " + 
				SnmpEngineId.createEngineId(trap.contextEngineId));
			println("\tContextName : " + new String(trap.contextName));
			println("\tVarBind list :");
			for(int i = 0; i < trap.varBindList.length; i++)
	    		println("oid : " + trap.varBindList[i].oid + " val : " + 
		    		trap.varBindList[i].value);
	
    }

 }

To Run the SyncManager Example
  1. In the examplesDir/Snmp/Manager directory, generate the OID table description of MIB-II that our manager will access.


    $ mibgen -mo mib_II.txt
    
  2. Compile the example classes.

    To set up your environment, see “Directories and Classpath” in the Preface.


    $ javac -classpath classpath -d . *.java
    
  3. Make sure that no other agent is running on port 8085, and start the simple SNMP agent in examplesDir/Snmp/Agent.

    See To Run the SNMPv1/v2 Agent Example if you have not already built and run this example.

    Type the following command to start the Agent example:


    $ cd examplesDir/Snmp/Agent
    $ java -classpath classpath Agent nbTraps
    

    If you are also running the asynchronous manager example with this agent, omit the nbTraps parameter. The agent then sends traps continuously and they can be seen in both managers. Otherwise, specify the number of traps to be sent to the manager. Wait until the manager is started to send the traps.

  4. Start the manager application in another window to connect to this agent.

    If you want to run the manager on a different host, replace localhost with the name of the host where you started the agent.


    $ cd examplesDir/Snmp/Manager
    $ java -classpath classpath SyncManager localhost 8085
    SyncManager::main: Send get request to SNMP agent on localhost at port 8085
    Result: 
    [Object ID : 1.3.6.1.2.1.1.1.0  (Syntax : String)
    Value : SunOS sparc 5.7]

    Here we see the output of the SNMP request, it is the value of the sysDescr variable on the agent.

  5. Press Enter in the agent's window.

    You should see the manager receiving the traps it sends. Leave the agent running if you are going on to the next example, otherwise remember to stop it by pressing Control-C.

To Run the SyncManagerV3 Example
  1. In the examplesDir/Snmp/Manager directory, generate the OID table description of MIB-II that our manager will access.


    $ mibgen -mo mib_II.txt
    
  2. Compile the example classes.

    To set up your environment, see “Directories and Classpath” in the Preface.


    $ javac -classpath classpath -d . *.java
    
  3. Make sure that no other agent is running on port 8085, and start the simple SNMPv3 agent, AgentV3, in examplesDir/Snmp/Agent.

    See To Run the SMNPv3 AgentV3 Example if you have not already built and run this example.

    Type the following commands to start the AgentV3 example:


    $ cd examplesDir/Snmp/Agent
    $ java -classpath classpath -Djdmk.security.file=./jdmk.security AgentV3
    
  4. Start the manager application in another window to connect to this agent.

    If you want to run the manager on a different host, replace localhost with the name of the host where you started the agent.


    $ cd examplesDir/Snmp/Manager
    $ java -classpath classpath -Djdmk.security.file=./jdmk.security 
    SyncManagerV3 localhost 8085
    

    Be sure to run the manager in its directory, otherwise it cannot find its jdmk.security file.

  5. Press Enter in the agent's window.

    You should see the manager receiving the traps it sends. Stop the manager by typing Control-C.

Synchronous Managers Accessing Several Agents

The SNMP API enables you to configure a synchronous SNMPv3 manager that can access several agents. The SyncManagerMultiV3 example demonstrates a simple SNMPv3 manager API that makes requests on two SNMPv3 agents. For the sake of simplicity, this manager does not listen for traps.


Example 19–5 SNMPv3 SyncManagerMultiV3 Example

	//Check host and port arguments
	//
        final String host1 = argv[0];
        final String port1 = argv[1];
			final String host2 = argv[2];
        final String port2 = argv[3];

        // Initialize the trace property. 

				[...]


            // Initialize the SNMP Manager API.
            // 
            final SnmpOidTableSupport oidTable = new RFC1213_MIBOidTable();
            SnmpOid.setSnmpOidTable(oidTable);
       
            [...]
	  
			    // Build the session. 
				//
	  			  try {
				// When instantiating a session, a new SNMP V3 engine is 
				// instantiated.
				//
					session= new SnmpSession("SyncManagerMultiV3 session");
	    		}catch(SnmpStatusException e) {
					println(e.getMessage());
					java.lang.System.exit(0);
			   }
	    		catch(IllegalArgumentException e) {
				// If the engine configuration is faulty
				//
				println(e.getMessage());
				java.lang.System.exit(0);
	    }
	
	    		// Get the SnmpEngine. 
			    //
			    final SnmpEngine engine = session.getEngine();
	    
	   			 // Create a SnmpPeer object for representing the first  
	    		 // entity to communicate with. 
	    	    //
	    		 final SnmpUsmPeer agent1 = 
				 new SnmpUsmPeer(engine, host1, Integer.parseInt(port1));
	    
	    		 //Create the second peer.
	    		 //
	   			final SnmpUsmPeer agent2 = 
				new SnmpUsmPeer(engine, host2, Integer.parseInt(port2));
	    
	    		// Create parameters to associate to the entity to  
	    		// communicate with.
	     	   //
	    		final SnmpUsmParameters p = 
				new SnmpUsmParameters(engine, "defaultUser");
	    
			   // Set security level to authNoPriv. 
			   //
		    	p.setSecurityLevel(SnmpDefinitions.authNoPriv);

	    		// Contextualize the send request
	    	   //
	    		p.setContextName("TEST-CONTEXT".getBytes());

	    		// Specify a contextEngineId 
		   		//
	    		p.setContextEngineId(agent1.getEngineId().getBytes());
	    
	    		// Associate the newly created parameter to the agent
		    	//
		    	agent1.setParams(p);
	
	    
	    		// Discover timeliness and boot
	    		agent1.processUsmTimelinessDiscovery();
	    
	    
	    		// Build the list of variables you want to query
	    		//
	    		final SnmpVarBindList list = 
				new SnmpVarBindList("SyncManagerMultiV3 varbind list");
	    
	    		// Read the "sysDescr" variable
	    		//
			   list.addVarBind("sysDescr.0");
	    
	    		// Make the SNMP get request on the first agent agent1 
	    		// and wait for the result
	    		//
	    		SnmpRequest request = 
				session.snmpGetRequest(agent1, null, list);
	    		println("SyncManagerMultiV3::main:" +
		    		" Send get request to SNMP agent on " + 
		    		host1 + " at port " + port1);
	    		boolean completed = request.waitForCompletion(10000);
	    
	    		// Check for a timeout
	    		//
            if (completed == false) {
                println("SyncManagerMultiV3::main:" +
						" Request timed out. Check if agent can 
						be reached");
		
                // Print request
                //
                println("Request: " + request.toString());
                java.lang.System.exit(0);
            }
	    
            // Check if the response contains an error 
	    		 //
            int errorStatus = request.getErrorStatus();
            if (errorStatus != SnmpDefinitions.snmpRspNoError) {
                println("Error status = " + 
						SnmpRequest.snmpErrorToString(errorStatus));
                println("Error index = " + 
						request.getErrorIndex());
                java.lang.System.exit(0);
            }
       
            // Display the content of the result
            //
            SnmpVarBindList result = request.getResponseVarBindList();
            println("Result: \n" + result);
       
            println("\n>> Press Enter if you want to send the request" +
		    " on the second agent.\n");
            java.lang.System.in.read();
            

	      		
			   // Repeat the process for the second agent agent2.
			   //
	    		SnmpUsmParameters p2 = 
				new SnmpUsmParameters(engine, "defaultUser");
	    
	    		p2.setSecurityLevel(SnmpDefinitions.authNoPriv);

	   			p2.setContextName("TEST-CONTEXT".getBytes());
	    
			   p2.setContextEngineId(agent2.getEngineId().getBytes());
	    
			   // Associate the updated parameters with agent2.
			   //
		      agent2.setParams(p2);
	    	    
	    		// Discover timeliness and boot
	    	   //
	    		agent2.processUsmTimelinessDiscovery();
	    
			  	// Make the request with agent2
			   //
	    		request = session.snmpGetRequest(agent2, null, list);
			    println("SyncManagerMultiV3::main:" +
		   			 " Send get request to SNMP agent on " + 
				    host2 + " at port " + port2);
				  completed = request.waitForCompletion(10000);
	    
	    		// Check for a timeout
	    		//
            if (completed == false) {
                println("SyncManagerMultiV3::main:" +
					" Request timed out. Check  if agent can be 
					reached");
		
                // Print request.
                //
                println("Request: " + request.toString());
                java.lang.System.exit(0);
            }
	    
           // Check if the response contains an error
	    		// 
	    		errorStatus = request.getErrorStatus();
           		 if (errorStatus != SnmpDefinitions.snmpRspNoError) {
               	 println("Error status = " + 
					SnmpRequest.snmpErrorToString(errorStatus));
               	 println("Error index = " + 
				request.getErrorIndex());
                java.lang.System.exit(0);
            }
       
            // Display the content of the result
            //
	    		result = request.getResponseVarBindList();
            println("Result: \n" + result);
       
            println("\n>> Press Enter if you want to stop " +
		    		"this manager.\n");
            java.lang.System.in.read();
	    
            // End the session
            //
            session.destroySession();
       
            
}

The SyncManagerMultiV3 example essentially performs the same actions as the SyncManagerV3 example, except it creates two SNMP USM peers rather than just one. The two peer agents are each created in exactly the same way as in the single peer example.

Both the peer agents are accessed using a common set of parameters, which are kept in the jdmk.security file for the session. This jdmk.security file contains two rows, one for each SNMP USM peer agent, as shown in the following example.


Example 19–6 jdmk.security File for the SyncManagerMultiV3 Example

#Authentication only.
userEntry=0x8000002a05819dcb6e00001f95,defaultUser,,usmHMACMD5AuthProtocol,
mypasswd
userEntry=0x8000002a05819dcb6e00001f96,defaultUser,,usmHMACMD5AuthProtocol,
mypasswd

# #####APPENDED PROPERTY####
localEngineBoots=5

# #####APPENDED PROPERTY####
localEngineID=0x8000002a05000000ec4c49ded9

If you configure your manager to create a greater number of peers, then its associated jdmk.security file must contain a corresponding number of entries, one for each authoritative engine with which the manager will communicate.

In this example, the only difference between the two userEntry rows is between the engine ID numbers. These engine IDs correspond to the engines of the two SNMP adaptor servers created by the MultipleAgentV3 example in Multiple Agents.

To Run the SyncManagerMultiV3 Example
  1. Before running the example, you must have run mibgen and compiled the Java classes in the examplesDir/Snmp/Manager directory.

    See To Run the SyncManager Example for instructions if you have not already done this.

  2. Make sure that no other agent is running, and start the multiple SNMPv3 agent, MultipleAgentV3, in examplesDir/Snmp/Agent.

    See Running the SNMPv3 MultipleAgentV3 Example if you have not already built and run this example.

    Type the following commands to start the MultipleAgentV3 example:


    $ cd examplesDir/Snmp/Agent
    $ java -classpath classpath -Djdmk.security.file=./jdmk.security 
    MultipleAgentV3
    

    The MultipleAgentV3 example simulates two SNMPv3 agents in one process. We shall make these agents peers of SyncManagerMultiV3.

    Be sure to run the multiple agent in its directory, otherwise it cannot find its jdmk.security and jdmk2.security files.

  3. Start the manager application in another window to connect to these two agents.

    If you want to run the manager on a different host from the one where the agents are running, replace localhost with the name of the host where you started the agents. Both the agents in the MultipleAgentV3 example run on the same host.


    $ cd examplesDir/Snmp/Manager
    $ java -classpath classpath -Djdmk.security.file=./jdmk.security 
    SyncManagerMultiV3 localhost 8085 localhost 8087
    

    Be sure to run the manager in its directory, otherwise it cannot find its jdmk.security file.

  4. You should see sending a request to the first agent. Press Enter to send a request to the second agent.

    You will now see the manager sending a second request to the agent on port 8087.

  5. Press Enter to stop the manager