记得之前说过一次关于SNMP4J 服务超时时间的问题 SNMP4J 服务端连接的超时时间 ,由于我们想保持这个连接的持续性,除非异常否则不能在服务端主动切断连接。
但是发现SNMP4J会主动丢掉一些连接,这个在日志中就能看到,这显然不合理。于是我设置了:
transport = new DefaultTcpTransportMapping((TcpAddress) listenAddress); transport.setConnectionTimeout(0);
但是我还说,并不是很了解他底层到底是干嘛的!后来仔细查看了 DefaultTcpTransportMapping 这个类,发现这个超时时间,其实只是在本地作为服务端时,巡检和清除指定连接的一个条件。
在他的类中有这样的一个属性:
private long connectionTimeout = 60000;
可以看看这个属性是做什么用的,首先在开始监听时,启动了一个连接清理服务对象:
public synchronized void listen() throws java.io.IOException { if (server != null) { throw new SocketException("Port already listening"); } serverThread = new ServerThread(); server = SNMP4JSettings.getThreadFactory().createWorkerThread("DefaultTCPTransportMapping_" + getAddress(), serverThread,true); if (connectionTimeout > 0) { socketCleaner = SNMP4JSettings.getTimerFactory().createTimer(); } server.run(); }
但是注意,这个对象启动的条件是你设置了超时时间,也就是connectionTimeout 大于 0 时。
往下找会找到一个内部类的子线程,他通过最后使用时间、超时时间、现在时间计算,来判定那个连接需要清理:
class SocketTimeout extends TimerTask { private SocketEntry entry; public SocketTimeout(SocketEntry entry) { this.entry = entry; } public void run() { long now = System.currentTimeMillis(); if ((socketCleaner == null) || (now - entry.getLastUse() >= connectionTimeout)) { if (logger.isDebugEnabled()) { logger.debug("Socket has not been used for " + (now - entry.getLastUse()) + " micro seconds, closing it"); } sockets.remove(entry.getPeerAddress()); try { synchronized (entry) { entry.getSocket().close(); } logger.info("Socket to " + entry.getPeerAddress() + " closed due to timeout"); } catch (IOException ex) { logger.error(ex); } } else { if (logger.isDebugEnabled()) { logger.debug("Scheduling " + ((entry.getLastUse() + connectionTimeout) - now)); } socketCleaner.schedule(new SocketTimeout(entry), (entry.getLastUse() + connectionTimeout) - now); } } public boolean cancel() { boolean result = super.cancel(); entry = null; return result; } }
可以看到,在超时之后,他会关闭连接,并且执行一行代码:
sockets.remove(entry.getPeerAddress());
会清理掉这个连接的缓存!
问题就在这里,如果你设置了超时时间是 0 ,那么这个清理就不会执行。你会想到他会在异常时处理,那么可以看一下他的服务类 ServerThread ,有这样的一段处理代码,并且他们也加了注释:
if (readChannel != null) { try { readMessage(sk, readChannel, incomingAddress); } catch (IOException iox) { // IO exception -> channel closed remotely if (logger.isDebugEnabled()) { iox.printStackTrace(); } logger.warn(iox); sk.cancel(); readChannel.close(); TransportStateEvent e = new TransportStateEvent(DefaultTcpTransportMapping.this, incomingAddress, TransportStateEvent. STATE_DISCONNECTED_REMOTELY, iox); fireConnectionStateChanged(e); } }
很明了他是想在远程异常连接关闭时做一些处理,但仅仅是做了一个状态改变的事件,并没有做移除缓存的操作。
如果进行测试,设置超时时间是 0 ,且使用工业交换机不断变换端口进行访问,发现缓存数量就一直增加。所以我的建议是,在这里增加清除某连接的缓存,很简单:
sockets.remove(incomingAddress);
后续:
因为修改后会移除链路缓存,但是后来多次测试发现,出来链路中断会在这里抛异常,垃圾数据的解析也会在这里抛异常。
BER解析消息长度的解析中就会报错,解析代码:
- public static final int decodeLength(BERInputStream is, boolean checkLength) throws IOException {
- int length = 0;
- int lengthbyte = is.read();
- if ((lengthbyte & ASN_LONG_LEN) > 0) {
- lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */
- if (lengthbyte == 0) {
- throw new IOException("Indefinite lengths are not supported");
- }
- if (lengthbyte > 4) {
- throw new IOException(
- "Data length > 4 bytes are not supported!");
- }
- for (int i = 0; i < lengthbyte; i++) {
- int l = is.read() & 0xFF;
- length |= (l << (8 * ((lengthbyte - 1) - i)));
- }
- if (length < 0) {
- throw new IOException(
- "SNMP does not support data lengths > 2^31");
- }
- } else { /* short asnlength */
- length = lengthbyte & 0xFF;
- }
- /**
- * If activated we do a length check here: length > is.available() ->
- * throw exception
- */
- if (checkLength) {
- checkLength(is, length);
- }
- return length;
如果这里报错,会在readMessage(sk, readChannel,incomingAddress)时报错,但不是链路问题,如果此时我们也安装链路中断处理就会有问题。
因此,我把解析头的代码专门try起来,发生问题就不解析,而不是向上层报错,链路断开时还是以前一样:
在读取消息的代码中:
- try {
- messageLength = messageLengthDecoder.getMessageLength(ByteBuffer.wrap(btnew));
- } catch (Exception e) {
- messageLength = null;
- logger.error(e);
- }
这个方法会调用dispatchMessage方法,这个方法也会调用解析函数,所以也要处理:
- try {
- fireProcessMessage(incomingAddress, bis);
- } catch (Exception e) {
- logger.error(e);
- }
我的策略是,有问题就不解决,不要向上层调用者反馈解析结果。
但是有链路断开时再进行反馈,也好让上层就是我们修改的代码知道出问题了,从而从缓存中移除链路信息。
请您到ITEYE看我的原创:http://cuisuqiang.iteye.com
或支持我的个人博客,地址:http://www.javacui.com
相关推荐
总的来说,SNMP4J-2.2.2-distribution.zip是一个全面的开发工具包,对于那些希望在Java环境中实现SNMP功能的开发者来说,它提供了必要的工具和资源,能够帮助他们构建高效且安全的网络管理系统。
标题和描述中提到的“SNMP4J-Agent-Guide”和“SNMP4J-Agent-Instrumentation-Guide”指向的是一份关于SNMP4J-Agent的指南文档,其中“SNMP4J Agent Guide”是标签部分。文档介绍了SNMP4J-Agent在SNMP协议的命令响应...
综上所述,SNMP4J-Doc-1.9.3d文档集是学习和使用SNMP4J库的重要资源,它涵盖了SNMP协议、SNMP4J库的使用方法、错误处理、性能优化等多个方面,对Java开发者进行网络管理软件开发非常有帮助。通过深入学习和实践,...
SNMP4J-Agentx是一个基于Java的开源工具,主要用于实现简单网络管理协议(SNMP)的代理功能。这个工具在SNMP4J项目下开发,是SNMP4J的一个扩展,提供了更丰富的功能和更方便的接口来创建和管理SNMP代理。SNMP4J-...
SNMP4J-Agent是SNMP(简单网络管理协议)的一个开源实现,专注于提供代理功能。这个版本2.0.6的发布包含了源码和API文档,对于开发者来说是一份宝贵的资源,可以深入理解SNMP协议的实现细节以及如何在Java环境中进行...
SNMP4J是一个Java实现的简单网络管理协议(SNMP)的开源库,它提供了全面的SNMP协议支持,包括v1、v2c和v3版本。在SNMP4J-2.7.0-distribution这个压缩包中,包含了最新的SNMP4J库的jar包和源代码,这对于开发者来说...
《深入理解SNMP4J 2.0.1:构建高效网络管理的基石》 SNMP4J 2.0.1是一个强大的Java库,专为实现简单网络管理协议(SNMP)而设计,用于在分布式环境中管理和监控网络设备。这个压缩包"snmp4j-2.0.1-distribution.zip...
SNMP4J是一个Java实现的简单网络管理协议(SNMP)开发库,它允许开发者创建SNMP代理和管理站应用程序。这个"snmp4j-2.5.8-distribution.zip"压缩包包含了SNMP4J库的jar文件以及源代码,方便开发者深入理解和自定义...
这个"snmp4j-2.5.7-distribution"版本是SNMP4J的一个发行版,包含了最新的2.5.7版本的库文件和其他相关资源,适用于那些需要在Java环境中处理网络管理任务的开发者。 SNMP,全称Simple Network Management Protocol...
SNMP4J是一个Java实现的SNMP协议库,使得Java开发者能够轻松地在应用程序中集成SNMP功能,从而对网络设备进行监控和管理。 SNMP4J.jar是这个库的核心组件,包含了SNMP协议的各种操作所需的类和方法。这个压缩包中的...
net-snmp所需的安装补丁包,NETSNMP程序补丁包net-snmp-devel-5.3.2.2-14.el5.x86_64.rpm
Snmp4j是一个开源的Java实现的简单网络管理协议(SNMP)库,它提供了SNMPv1、SNMPv2c以及SNMPv3的支持。这个“snmp4j-2.0.3-distribution.zip”文件包含了该库的最新版本2.0.3,适合用于开发和管理网络设备,监控...
无论是小型的家庭网络还是大型的企业网络,SNMP4j-Agent都能够提供可靠的网络监控和管理能力,从而提升整体网络环境的稳定性和安全性。在实际操作中,理解并熟练运用SNMP4j-Agent的各种特性,无疑会极大地提高网络...
4. **安装SNMP服务**:在所有依赖包安装完成后,使用`rpm -ivh snmp-*.rpm`安装SNMP服务。 5. **配置SNMP**:SNMP的配置文件通常位于`/etc/snmp/snmpd.conf`。你需要根据需求编辑这个文件,例如设置社区字符串...
SNMP4J是一个基于Java语言实现的简单网络管理协议(SNMP)的开源库,它为开发者提供了在Java环境中开发SNMP应用的全面支持。SNMP是网络设备管理和监控的标准协议,广泛应用于网络设备配置、性能监控以及故障排查等...
总之,SNMP4J-Agent提供了一个强大的平台,让开发者能够在本地环境中模拟SNMP网络环境,极大地简化了测试和学习过程。通过熟练掌握SNMP4J-Agent的使用,你将能够更好地理解和应用SNMP协议,提升网络管理的效率。
SNMP4J-Agent是SNMP4J项目的一部分,它是一个开放源码的Java实现,用于构建SNMP代理(Agent)应用程序。SNMP(简单网络管理协议)是一种广泛使用的网络管理协议,允许网络管理员监控和配置网络设备。SNMP4J-Agent...
SNMP(简单网络管理协议)是一种广泛应用于网络设备管理的标准协议,而SNMP4J-Agent则是SNMP4J项目的一部分,专为Java开发者提供了一套实现SNMP代理功能的库。本文将深入探讨SNMP4J-Agent 1.4.1版本的关键特性、应用...
通过SNMP4j,开发者可以设置监听器来接收并处理来自设备的TRAP消息,从而实时了解网络状况。TRAP通常包含触发事件的设备的OID(对象标识符)、事件类型和其他相关数据。 4. Java实现:SNMP4j库是用Java语言编写的,...
SNMP安装包-net-snmp-utils-5.7.2-49.el7_9.2.x86_64