SNMP4J服务端连接超时问题解决方案

2022-07-29,,,

我们的网络管理中心作为管理中心,是服务端!各个被管设备通过交换机作为客户端与网管中心进行通信,使用的tcp/ip协议!

snmp只是一种协议包,snmp4j作为snmp使用的java工具包,提供了方便安全的工具包功能!

但是在使用中发现一个问题就是,服务端与客户端发送消息时,发送数次后就不再发送数据了!网络抓包也抓不到,跟踪断点到snmp4j的代码中发现了这样一个问题!

	/**
	 * sends a snmp message to the supplied address.
	 * 
	 * @param address
	 *      an <code>tcpaddress</code>. a
	 *      <code>classcastexception</code> is thrown if
	 *      <code>address</code> is not a <code>tcpaddress</code>
	 *      instance.
	 * @param message
	 *      byte[] the message to sent.
	 * @throws ioexception
	 */
	public void sendmessage(address address, byte[] message)
			throws java.io.ioexception {
		if (server == null) {
			listen();
		}
		serverthread.sendmessage(address, message);
	}

我们可以看到,他与udp的不同是,使用了一个服务的线程!

	public void sendmessage(address address, byte[] message)
			throws java.io.ioexception {
		socket s = null;
		socketentry entry = (socketentry) sockets.get(address);
		if (logger.isdebugenabled()) {
			logger.debug("looking up connection for destination '"
					+ address + "' returned: " + entry);
			logger.debug(sockets.tostring());
		}
		if (entry != null) {
			s = entry.getsocket();
		}
		if ((s == null) || (s.isclosed()) || (!s.isconnected())) {
			if (logger.isdebugenabled()) {
				logger.debug("socket for address '" + address
						+ "' is closed, opening it...");
			}
			pending.remove(entry);
			socketchannel sc = null;
			try {
				// open the channel, set it to non-blocking, initiate
				// connect
				sc = socketchannel.open();
				sc.configureblocking(false);
				sc
						.connect(new inetsocketaddress(
								((tcpaddress) address).getinetaddress(),
								((tcpaddress) address).getport()));
				s = sc.socket();
				entry = new socketentry((tcpaddress) address, s);
				entry.addmessage(message);
				sockets.put(address, entry);
	
				synchronized (pending) {
					pending.add(entry);
				}
	
				selector.wakeup();
				logger.debug("trying to connect to " + address);
			} catch (ioexception iox) {
				logger.error(iox);
				throw iox;
			}
		} else {
			entry.addmessage(message);
			synchronized (pending) {
				pending.add(entry);
			}
			selector.wakeup();
		}
	}

他从一个map中去获得连接 socketentry ,然后得到连接对象socket!

判断socket是否有效,有效则直接发送,无效则创建连接后再发送!

然后我找到这样一段代码

private synchronized void timeoutsocket(socketentry entry) { 
  if (connectiontimeout > 0) { 
    socketcleaner.schedule(new sockettimeout(entry), connectiontimeout); 
  } 
} 

也就是说服务端会自己检查的连接并且去清除他!

我尝试设置 connectiontimeout 的值

private void init() throws unknownhostexception, ioexception { 
  threadpool = threadpool.create("trap", 2); 
  dispatcher = new multithreadedmessagedispatcher(threadpool,new messagedispatcherimpl()); 
  // 本地ip与监听端口 
  listenaddress = genericaddress.parse(system.getproperty("snmp4j.listenaddress", "tcp:192.168.9.69/5055")); 
  defaulttcptransportmapping transport; 
  transport = new defaulttcptransportmapping((tcpaddress) listenaddress); 
  transport.setconnectiontimeout(0); 
  snmp = new snmp(dispatcher, transport); 
  snmp.getmessagedispatcher().addmessageprocessingmodel(new mpv1()); 
  snmp.getmessagedispatcher().addmessageprocessingmodel(new mpv2c()); 
  snmp.getmessagedispatcher().addmessageprocessingmodel(new mpv3()); 
  usm usm = new usm(securityprotocols.getinstance(), new octetstring(mpv3.createlocalengineid()), 0); 
  securitymodels.getinstance().addsecuritymodel(usm); 
  snmp.listen(); 
} 

增加一行代码 设置defaulttcptransportmapping的超时时间是 0 !

然后就没有问题了!

虽然临时解决了问题,但是由于对snmp4j不够深入了解,我怕问题恐怕不是这样的!

我在此也希望使用snmp4j为工具,且作为服务端,在发送数据时有问题的解决方法!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

《SNMP4J服务端连接超时问题解决方案.doc》

下载本文的Word格式文档,以方便收藏与打印。