欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-08 10:05:26
我们的网络管理中心作为管理中心,是服务端!各个被管设备通过交换机作为客户端与网管中心进行通信,使用的tcp/ip协议!snmp只是一种协议包,snmp4j作为snmp使用的java工具包,提供了方便安...

我们的网络管理中心作为管理中心,是服务端!各个被管设备通过交换机作为客户端与网管中心进行通信,使用的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为工具,且作为服务端,在发送数据时有问题的解决方法!

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