`
cuisuqiang
  • 浏览: 3956230 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
3feb66c0-2fb6-35ff-968a-5f5ec10ada43
Java研发技术指南
浏览量:3666773
社区版块
存档分类
最新评论

SNMP 修改SNMP4J消息内容

    博客分类:
  • J2EE
阅读更多

我记得上次就有人说我这种做法

 

上次是因为我要在SNMP4J协议消息中增加两个特殊的OID来做为参数传递,遭到一些人质疑,认为是无用的

其实别的不说,我只想说一句:业务要求你这样你能怎么得,别跟我扯技术

 

我预计这次又得早质疑了,不过质疑你们就质疑吧,我们这次要求就是这样的

因为我们和远端机器调用时他们需要做数据流截取,所以我们必须打包一下我们这个SNMP协议包的大小

就是说这次的需求是,在SNMP协议原来基础上,发送消息时增加两个字节的消息长度信息

 

先来说发送时

其实SNMP我理解的话就是一种消息格式,最后还是通过TCP或UDP发送的,默认是通过UDP发送的

你通过Snmp的send方法一直向下找,可以看到

 

 你到DefaultUdpTransportMapping这个类中看即可

 

他的sendMessage方法负责把组装后的SNMP消息包,根据地址,使用UDP协议发送出去

 

  public void sendMessage(Address targetAddress, byte[] message)
      throws java.io.IOException
  {
    InetSocketAddress targetSocketAddress =
        new InetSocketAddress(((UdpAddress)targetAddress).getInetAddress(),
                              ((UdpAddress)targetAddress).getPort());
    if (logger.isDebugEnabled()) {
      logger.debug("Sending message to "+targetAddress+" with length "+
                   message.length+": "+
                   new OctetString(message).toHexString());
    }
    DatagramSocket s = ensureSocket();
    s.send(new DatagramPacket(message, message.length, targetSocketAddress));
  }

 

所以要修改SNMP4J发送的内容,在这里下手

message[] 数组就是发送的内容,这里我们做下手脚

/**
 * 使用UDP发送消息
 * 崔素强进行修改,增加了消息长度字段,占用两个字节
 */
public void sendMessage(Address targetAddress, byte[] message)
		throws java.io.IOException {		
	// TODO 增加头字段
	short length = (short)message.length;
	byte[] btlength = shortToByte(length);
	byte[] relmess = new byte[message.length + 2];		
	ByteBuffer bbuf = ByteBuffer.allocate(message.length + 2);
	bbuf.put(btlength);
	bbuf.put(message);
	bbuf.flip();
	bbuf.get(relmess, bbuf.position(), bbuf.limit()); // 得到目前为止缓冲区所有的数据		
	InetSocketAddress targetSocketAddress = new InetSocketAddress(
			((UdpAddress) targetAddress).getInetAddress(),
			((UdpAddress) targetAddress).getPort());
	if (logger.isDebugEnabled()) {
		logger.debug("Sending message to " + targetAddress
				+ " with length " + relmess.length + ": "
				+ new OctetString(relmess).toHexString());
	}
	DatagramSocket s = ensureSocket();
	s.send(new DatagramPacket(relmess, relmess.length,targetSocketAddress));
}

 

简单修改为他的消息包增加了头消息长度属性

 

为了看效果,你可能会马上去运行一下,但是你不能这么做,修改之后的消息包已经不再“正确”,SNMP4J会进行一下检查,如果不对是不可能解析的

所以我们在接收消息时要除掉头消息

 

还是这个类,他有一个内部类 ListenThread 是一个线程类用来监听消息

while (!stop) {
DatagramPacket packet = new DatagramPacket(buf, buf.length,
										   udpAddress.getInetAddress(),
										   udpAddress.getPort());
try {
  try {
	socket.receive(packet);
  }
  catch (InterruptedIOException iiox) {
	if (iiox.bytesTransferred <= 0) {
	  continue;
	}
  }
  if (logger.isDebugEnabled()) {
	logger.debug("Received message from "+packet.getAddress()+"/"+
				 packet.getPort()+
				 " with length "+packet.getLength()+": "+
				 new OctetString(packet.getData(), 0,
								 packet.getLength()).toHexString());
  }
  ByteBuffer bis;
  // If messages are processed asynchronously (i.e. multi-threaded)
  // then we have to copy the buffer's content here!
  if (isAsyncMsgProcessingSupported()) {
	byte[] bytes = new byte[packet.getLength()];
	System.arraycopy(packet.getData(), 0, bytes, 0, bytes.length);
	bis = ByteBuffer.wrap(bytes);
  }
  else {
	bis = ByteBuffer.wrap(packet.getData());
  }
  fireProcessMessage(new UdpAddress(packet.getAddress(),
									packet.getPort()), bis);
}
catch (SocketTimeoutException stex) {
  // ignore
}
catch (PortUnreachableException purex) {
  synchronized (DefaultUdpTransportMapping.this) {
	listener = null;
  }
  logger.error(purex);
  if (logger.isDebugEnabled()) {
	purex.printStackTrace();
  }
  if (SNMP4JSettings.isFowardRuntimeExceptions()) {
	throw new RuntimeException(purex);
  }
  break;
}
catch (SocketException soex) {
  if (!stop) {
	logger.error("Socket for transport mapping " + toString() +
				 " error: " + soex.getMessage(), soex);
  }
  stop = true;
}
catch (IOException iox) {
  logger.warn(iox);
  if (logger.isDebugEnabled()) {
	iox.printStackTrace();
  }
  if (SNMP4JSettings.isFowardRuntimeExceptions()) {
	throw new RuntimeException(iox);
  }
}
}

 

他搞了一个缓冲区来包装返回的消息内容,然后给了一个方法,我们就在这里处理

// TODO 移除头字段
ByteBuffer bis;
if (isAsyncMsgProcessingSupported()) {
	byte[] bytes = new byte[packet.getLength() - 2];
	System.arraycopy(packet.getData(), 2, bytes, 0,bytes.length);
	bis = ByteBuffer.wrap(bytes);
} else {
	byte[] bytes = new byte[packet.getData().length - 2];
	System.arraycopy(packet.getData(), 2, bytes, 0,bytes.length);
	bis = ByteBuffer.wrap(bytes);
}

fireProcessMessage(new UdpAddress(packet.getAddress(),
		packet.getPort()), bis);

 

这样就可以运行测试,发现没有影响,但是如果你查看发送的字节流就会发现增加了两个字节

 

相关人不要质疑了,需求就是这样的,没办法,我已经很不容易了!

 

请您到ITEYE看我的原创:http://cuisuqiang.iteye.com

或支持我的个人博客,地址:http://www.javacui.com

 

  • src.zip (384.2 KB)
  • 下载次数: 25
分享到:
评论
3 楼 cuisuqiang 2012-08-23  
特别提醒
如果您使用了TCP方式发送,那么请不要使用这种方法进行发送,否则不能接收到消息!
2 楼 cuisuqiang 2012-08-23  
修正:
  public void sendMessage(Address targetAddress, byte[] message)
      throws java.io.IOException
  {
    InetSocketAddress targetSocketAddress =
        new InetSocketAddress(((UdpAddress)targetAddress).getInetAddress(),
                              ((UdpAddress)targetAddress).getPort());
    if (logger.isDebugEnabled()) {
      logger.debug("Sending message to "+targetAddress+" with length "+
                   message.length+": "+
                   new OctetString(message).toHexString());
    }
    DatagramSocket s = ensureSocket();
    
    // TODO 增加头字段
	short length = (short)(message.length + 2);
	byte[] btlength = shortToByte(length);
	byte[] relmess = new byte[length];
	System.arraycopy(btlength, 0, relmess, 0, 2);
	System.arraycopy(message, 0, relmess, 2, message.length);
    
    s.send(new DatagramPacket(relmess, relmess.length, targetSocketAddress));
  }

发送时增加头字节不要使用ByteBuffer 直接使用字节流拷贝,不然有内存问题
1 楼 cuisuqiang 2012-07-10  
附件是SNMP4J的源码,源码是没有修改过的,仅供参考

相关推荐

    基于SNMP4J的SNMP操作实现代码

    SNMP4J是一个开源的Java库,提供了一个完整的SNMP实现,包括PDU构造、消息编码和解码、错误处理等功能。它支持SNMPv1、v2c和v3的安全性和认证机制。使用SNMP4J,开发者可以轻松地在Java应用中集成SNMP功能。 3. ...

    snmp4j.rar_SNMP_SNMP4J.jar_snmp4j的jar包_网络设备监控

    1. **Trap接收与发送**:SNMP陷阱(Trap)是网络设备向管理站主动发送的报警消息,SNMP4J支持设置陷阱监听器来接收这些消息,同时也能主动发送自定义陷阱。 2. **Get请求与Response**:通过GET操作,可以获取网络...

    使用Java进行SNMP编程-SNMP4J-代码实例

    使用SNMP4J,开发者能够通过编写Java代码来实现对网络设备的操作,比如检索设备信息、修改设备配置、接收告警通知等。 在这份文档中,提到了几个SNMP4J中实现的操作,包括GET、GETNEXT、GETBULK、Walk和SET。 GET...

    SNMP实例大全--snmp4j(get ,trap,set,取mib)

    通过上述内容,你应能掌握使用snmp4j库进行SNMP操作的基本方法,包括获取和设置MIB值,发送TRAP,以及在SNMPv3环境下的安全配置。这个eclipse工程提供了一个实用的起点,帮助你开始在Java项目中集成SNMP功能。

    如何利用snmp4j-agent在PC端模拟snmp服务

    本文将深入探讨如何使用SNMP4J-Agent工具在个人计算机上模拟SNMP服务,以便进行测试和开发。 SNMP4J-Agent是SNMP4J项目的一部分,是一个开源的Java库,用于实现SNMP代理功能。它提供了丰富的API,可以方便地构建...

    snmp.zip_SNMP4J MIB_java mib_mib_mib snmp4j_snmp模拟

    此外,还可以通过SNMP4J的NotificationOriginator接口发送Trap或Inform消息,以通知管理站网络设备的状态变化。 在提供的压缩文件列表中,"www.pudn.com.txt"可能是一个包含更多关于SNMP4J使用示例或MIB模拟细节的...

    java利用snmp4j包来读取snmp协议数据

    SNMP4J是一个开源的Java库,专门设计用于实现SNMP协议的客户端功能,使得开发者能够从网络设备中读取或设置管理信息。本篇文章将详细探讨如何使用SNMP4j库在Java中读取SNMP协议数据。 首先,了解SNMP是必要的。SNMP...

    snmp4j-1.9.3d.zip_snmp4j-1.9.3d_snmp管理工具

    SNMP4J提供了丰富的类和接口,如`Snmp`类用于发起SNMP请求,`Target`类定义了SNMP操作的目标,`PDU`类表示SNMP消息中的数据单元。 例如,以下是一个简单的SNMP GET请求的示例: ```java import org.snmp4j.*; ...

    snmp4j学习文档

    四、SNMP4J基本操作 使用SNMP4J,开发者可以执行以下基本操作: 1. Get:获取MIB对象的值。 2. Set:修改MIB对象的值。 3. GetNext:获取下一个MIB对象的值,用于遍历MIB树。 4. Trap:接收或发送陷阱(Trap)报文,...

    SNMP4j.rar_snmp java_snmp4j_snmp4j demo

    SNMP4j是一个Java库,专门用于实现简单网络管理协议(SNMP)的应用程序。SNMP是一种广泛应用于网络设备管理的标准协议,它允许系统管理员远程监控和管理网络设备,如路由器、交换机、服务器等。SNMP4j是Java开发者在...

    SNMP4J 的jar包

    `snmp4j-2.2.2.jar`是SNMP4J的主要库,包含了SNMP协议的实现,如PDU(Protocol Data Unit)的创建、消息处理、安全模型和认证机制。此版本支持SNMPv1、v2c和v3,提供了对不同安全级别的支持,包括无认证、基于密码的...

    SNMP4j帮助文件

    SNMP4j是一款开源的Java库,专门用于实现简单网络管理协议(SNMP)的应用程序。这个库使得Java开发者能够轻松地与支持SNMP的网络设备进行通信,从而监控、管理和配置网络基础设施。"SNMP4j帮助文件"是针对这款库的...

    使用snmp4j实现Snmp功能

    除了GET请求,`snmp4j` 还支持其他SNMP操作,如SET请求(用于修改设备配置)和Trap(用于接收设备发送的事件通知)。此外,`snmp4j` 提供了完整的SNMP版本支持,包括安全性增强的SNMPv3,可以设置安全模型、认证协议...

    snmp4j中agent程序demo

    在这个“snmp4j中agent程序demo”中,我们将探讨SNMP代理的基本概念、Snmp4j库的使用以及如何创建一个简单的SNMP代理程序。 首先,理解SNMP代理的概念是至关重要的。SNMP代理是网络设备上的软件组件,负责收集设备...

    snmp4j入门实例+snmp4j.jar+XPsnmp安装包

    在SNMP4J中,首先需要设置一个TransportMapping,如UDPTransportMapping,它定义了SNMP消息的传输方式。接着,创建一个Session对象,绑定到TransportMapping,以建立与远程设备的连接。然后,可以使用PDU(Protocol ...

    snmp4j包来读取snmp协议数据

    在Java环境中,我们通常会借助第三方库来处理SNMP协议,其中“snmp4j”是一个功能强大的开源库,专门用于实现SNMP协议的客户端功能。 snmp4j库提供了丰富的API,使得开发者能够轻松地与支持SNMP协议的设备进行通信...

    snmp4j-2.5.6_SNMP4J.jar_

    **SNMP4J:网络管理的利器** SNMP4J是一个用Java编写的开放源码的简单网络管理协议(SNMP)实现库。这个库允许开发者构建能够与SNMP兼容的网络设备进行通信的应用程序。SNMP4J-2.5.6版本是其重要的里程碑,提供了对...

    SNMP4J-CLT

    SNMP4J-CLT是基于Java开发的一个强大的命令行工具,它允许用户与支持SNMP(简单网络管理协议)的设备进行交互。这个工具在任何支持Java的平台上都能运行,包括Windows、Linux、macOS等,这得益于Java的跨平台特性。...

Global site tag (gtag.js) - Google Analytics