What do snmp close method really mean?Why I have so many udp connection after close snmp gettable client?

I need to periodically query the oid results with multiple threads. Every time I query, I will create a new snmp clent and finally close snmp. However, I found that the number of UDP connections will be more and more, with thousands of incremental connections. The final process leads to the inability to ping the local machine. Can I use only one SNMP client in multithreading? Will this lead to inefficiency or uncorrect result?

Snmp snmp = null;
   Target target = null;
   	try {
   		snmp = SnmpComunication.getSnmp(snmpTarget.getSnmpVersion());
   		target = new CommunityTarget();
   		((CommunityTarget) target).setCommunity(new OctetString(snmpTarget.getReadCommunity())); 
                       DefaultPDUFactory defaultPDUFactory =  new DefaultPDUFactory(PDU.GETBULK); 
       if (target instanceof UserTarget) {
           OctetString contextEngineId = new OctetString("");
           OctetString contextName = new OctetString("");
           defaultPDUFactory.setContextName(contextName);
           defaultPDUFactory.setContextEngineID(contextEngineId);
       }
   		tableUtils = new TableUtils(snmp, defaultPDUFactory);
   		tableUtils.setIgnoreMaxLexicographicRowOrderingErrors(300); 
   		List<VariableBinding[]> returnList = new ArrayList<VariableBinding[]>();
   			List<VariableBinding[]> resultList=new ArrayList<>();
   			OID[] columns = new OID[oids.size()];
   			for (int i = 0; i < oids.size(); i++) {
   				columns[i] = new OID(oids.get(i));
   			}
   			List<TableEvent> events = null; 
   			try {
   				events = tableUtils.getTable(target, columns, null, null);
   			} catch (Exception exception) {
   				logger.error("getTable exception:" + exception.getMessage());
   			}

   			if (events == null || (events.size() == 1 && events.get(0).getColumns() == null)) {
   				throw new Exception("Gettable result is null" );
   			} else {
   				 	for (TableEvent event : events) { 
   					if (event.getException() != null) {
   					 	throw new Exception(event.getErrorMessage() + "," + event.getException().getMessage());
   					}
   					if (event.getColumns() == null || event.getColumns().length < 1) {
   						continue;
   					} 
   					VariableBinding[] values = event.getColumns();
   					returnList.add(values);
   				}
   			}  
   		return returnList;
   	} catch (Exception e) { 
   		throw new Exception("error");
   	} finally {
   		 if (snmp != null) {
   			snmp.close(); 
   	}
   	}

   	public static Snmp getSnmp(Integer version) {
   	try {
   		TransportMapping transport = new DefaultUdpTransportMapping();
   		Snmp snmp = new Snmp(transport);
   		if (version == MessageProcessingModel.MPv3) {
   			if (snmp.getUSM() == null) {
   				byte[] localEngineID = MPv3.createLocalEngineID();
   				engineId = new OctetString(localEngineID);
   				USM usm = new USM(SecurityProtocols.getInstance(), engineId, 0);
   				SecurityModels.getInstance().addSecurityModel(usm);
   			}
   		}
   		transport.listen();
   		return snmp;
   	} catch (Exception e) { 
   	}
   	return null;
   }

The short answer is:

  • Reuse TransportMappings and of course the Snmp instance as often as possible!
  • Creating a new Snmp instance per message is total overkill!
  • Snmp.close closes all TransportMappings by calling their close methods, but the operating system will not be fast enough to free the associated ports, because those need a grace period to be reassigned (to avoid packets to be delivered to the wrong process and maybe for other reasons)
  • A “multi-threaded” application that creates ports (= TransportMapings) to send single or few messages will be slower than a single threaded application reusing ports by many factors!
  • Something like a “UDP connection” will never exits, because UDP is connectionless.

Personal remark: There seems to be a misunderstanding about ‘multi-threading’ in parts of the programming community for more than twenty years that many threads make everything faster - unfortunately the opposite is true most of the time…

Every 10 minutes, I have tens of thousands of device OIDs to query, so I have to use multithreading to query.

If multiple threads use only two snmp instance by calling getSnmp(MessageProcessingModel.MPv3) and getSnmp(MessageProcessingModel.MPv2), some are used to query gettable oid and some are used to query walk or getnext oid, do I need to do additional operations to ensure thread safety (that is, the execution results of multiple threads will not affect each othe)?

Not necessarily. Asynchronous processing could be sufficient. It all depends on how complex the response processing is. But that is independent of the SNMP protocol part.

No.You must only ensure that you do not modify the PDU that you are sending while it is being processed.

Do my code is asynchronous or not? I do not understant Asynchronous processing is asynchronous processing a request method for gettable or a result of gettable.

What do you mean by this sentence,please?As the code shows, in each thread, I call tableUtils = new TableUtils(snmp, defaultPDUFactory); events = tableUtils.getTable(target, columns, null, null);,just columns(oid) and target ip is different but snmp client instance may be the same one,and then process the result. Is that means I modify the ‘PDU’?

Your code does synchronous request processing.