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

SNMP 修改SNMP4J消息内容 之TCP发送模式

阅读更多

之前写了一篇关于 SNMP 修改SNMP4J消息内容 的博客,但是当时只是针对UDP的,后来应用到TCP上后发现有一些问题,现在说一下解决方法

上一篇连接地址:http://cuisuqiang.iteye.com/blog/1584391 

 

使用TCP发送时,由于Socket不知道数据流的长度,所以要增加数据包长度到包上,这才是真正的需求,是我上次理解错了

增加头信息与上一次一样,直接在发送时增加即可

 

找到类:DefaultTcpTransportMapping

找到发送方法:

public void sendMessage(Address address, byte[] message)

 

在发送时增加消息头 

  /**
   * 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();
    }
	// 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);
	
	serverThread.sendMessage(address, relmess);
  }

 

但是在接收时就遇到一个问题,底层接收后会直接验证数据流,如果你增加头信息,就不算是标准SNMP包了,SNMP4J就不会接收不会处理

 

在类:DefaultTcpTransportMapping 中有一个内部类:

class ServerThread implements WorkerTask 

 

方法

private void readMessage(SelectionKey sk, SocketChannel readChannel,
                             TcpAddress incomingAddress) throws IOException 

 

提供对于数据流的处理,处理后将数据流返回到上层进行解析

 

在方法中有这样有这样的代码:

  ByteBuffer byteBuffer = ByteBuffer.wrap(buf);
  byteBuffer.limit(messageLengthDecoder.getMinHeaderLength());

 

MessageLengthDecoder 接口用于标识SNMP数据包的一些属性解析方法,包括最小头字节和获得 MessageLength 对象

如果数据小于最小字节,那么直接抛弃不解析

同样在TCP发送类中有一个内部类来实现这个接口:

  public static class SnmpMesssageLengthDecoder implements MessageLengthDecoder {
    public int getMinHeaderLength() {
      return MIN_SNMP_HEADER_LENGTH;
    }
    public MessageLength getMessageLength(ByteBuffer buf) throws IOException {
      MutableByte type = new MutableByte();
      BERInputStream is = new BERInputStream(buf);
      int ml = BER.decodeHeader(is, type);
      int hl = (int)is.getPosition();
      MessageLength messageLength = new MessageLength(hl, ml);
      return messageLength;
    }
  }

 

由于我们增加两个字节的长度,所以要重新写一个实现的接口

  // TODO 自己定义的头解析
  public static class SnmpMesssageLengthDecoderMe implements MessageLengthDecoder {	  
	    public int getMinHeaderLength() {
	      return MIN_SNMP_HEADER_LENGTH + 2;
	    }
	    public MessageLength getMessageLength(ByteBuffer buf) throws IOException {
	         int hl = 4;
	         int ml = decodeHeader(buf);
	         MessageLength messageLength = new MessageLength(hl, ml);
	         return messageLength;
	    }	    
	    public int decodeHeader(ByteBuffer is){
	    	byte[] bt = is.array();
	    	byte[] len = new byte[]{ bt[0], bt[1] };
	    	return byteToShort(len) - 4;
	    }	    
	    /**
		 * @功能 字节的转换与短整型
		 * @return 短整型
		 */
		public synchronized static short byteToShort(byte[] b) {
			short s = 0;
			short s0 = (short) (b[1] & 0xff);// 最低位
			short s1 = (short) (b[0] & 0xff);
			s1 <<= 8;
			s = (short) (s0 | s1);
			return s;
		}
  }

 

 长度就是原来的 +2 ,MessageLength 的属性有两个,按照我的写法写可以解决问题,但是我不明白

int ml = BER.decodeHeader(is, type);

 

的含义,希望有明白的给说明一下

消息的长度实际上就是我们定义的头表示的长度 -4

这样流读取方法才能把我们发送的数据流完整读取出来

 

上次在转发到上层解析时的方法也要修改,因为现在修改的只是正常读取到所有的流,而返给上层的数据流是要截取掉这两个字节的

    @SuppressWarnings("static-access")
	private void dispatchMessage(TcpAddress incomingAddress,
                                 ByteBuffer byteBuffer, long bytesRead) {
      byteBuffer.flip();
      if (logger.isDebugEnabled()) {
        logger.debug("Received message from " + incomingAddress +
                     " with length " + bytesRead + ": " +
                     new OctetString(byteBuffer.array(), 0,
                                     (int)bytesRead).toHexString());
      }
      ByteBuffer bis;
      if (isAsyncMsgProcessingSupported()) {
        byte[] bytes = new byte[(int)bytesRead - 2];
        System.arraycopy(byteBuffer.array(), 2, bytes, 0, (int)bytesRead - 2);
        bis = ByteBuffer.wrap(bytes);
      }
      else {
    	  byte[] bytes = new byte[(int)bytesRead - 2];
          System.arraycopy(byteBuffer.array(), 2, bytes, 0, (int)bytesRead - 2);
          bis = ByteBuffer.wrap(bytes);
      }
		      
      // TODO 调用解析数据流
      fireProcessMessage(incomingAddress, bis);
    }

 

这样就可以正常解析增加两个字节的数据包

 

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

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

 

1
5
分享到:
评论
1 楼 cuisuqiang 2012-08-24  
不好意思经过测试,以上代码存在问题!
由于TCP传输可能不是一次性传输的,另外,运行设备在一些情况下会产生垃圾数据,因此必须对接收的数据进行验证,所以在复写MessageLengthDecoder接口时,不能过分改动:
  public static class SnmpMesssageLengthDecoderMe implements MessageLengthDecoder {
	  
	    public int getMinHeaderLength() {
	      return MIN_SNMP_HEADER_LENGTH + 2;
	    }
	    
	    public MessageLength getMessageLength(ByteBuffer buf) throws IOException {
	    	MutableByte type = new MutableByte();
	        BERInputStream is = new BERInputStream(buf);
	        int ml = BER.decodeHeader(is, type);
	        int hl = (int)is.getPosition() + 2;
	        MessageLength messageLength = new MessageLength(hl, ml);
	        return messageLength;
	    }
  }

我们只改动头字节长度一项,另外getMessageLength方法也稍微修改


而在调用方法时传递的字节流我们把头给截取即可
// TODO 信息转换
byte[] btnew = new byte[buf.length];
System.arraycopy(buf, 2, btnew, 0, buf.length - 2);
messageLength = messageLengthDecoder.getMessageLength(ByteBuffer.wrap(btnew));

相关推荐

    snmp4j实现snmp trap 发送与接收

    使用 SNMP4J 库可以轻松地实现 SNMP Trap 发送和接收,且支持多种传输协议,如 UDP 和 TCP。 Trap 发送 在 SNMP4J 库中,Trap 发送可以通过使用 `Snmp` 对象和 `CommandResponder` 接口来实现。`Snmp` 对象用于...

    基于SNMP4J的SNMP操作实现代码

    在SNMP4J中,你可以创建一个GetRequest PDU,指定要查询的对象标识符(OID),然后通过Transport(如UDP或TCP)发送请求。收到响应后,解析PDU获取结果。 4. GETNEXT操作: GETNEXT操作用于获取MIB中给定对象的下...

    snmp4j.zip_java使用snmp4j_snmp4j_snmp4j java

    在提供的“snmp4j.pdf”文档中,你将找到更多关于如何使用SNMP4J的详细示例和教程,包括初始化设置、发送请求、处理响应、以及设置陷阱监听器等内容。这份文档将帮助你深入理解和应用SNMP4J库,以便在Java环境中有效...

    snmp4j api文档

    **SNMP4J API文档详解** SNMP4J是一个开源的Java实现的简单网络管理协议(SNMP)库,它提供了全面的API用于开发SNMP应用程序。本文将深入解析SNMP4J API的核心概念和主要功能,帮助开发者理解和利用这个强大的工具...

    SNMP4J重要的类和接口的介绍.doc

    SNMP4J 支持两种消息发送模式:同步发送模式和异步发送模式。同步发送模式也称阻塞模式,当管理端发送出一条消息之后,线程会被阻塞,直到收到对方的回应或者时间超时。异步发送模式也称非阻塞模式,当程序发送一条...

    snmp4j的jar包

    4. **发送PDU**:通过Session对象发送Get、Set或Trap请求,SNMP4J会自动封装这些请求为适当的PDU格式。 5. **处理响应**:定义事件监听器来处理接收到的响应,包括成功返回的数据、错误信息或者陷阱通知。 SNMP4J还...

    snmp4j源码和API

    接着,`Snmp`类是SNMP4J的核心,它实现了SNMP协议引擎,处理SNMP请求和响应的发送与接收。`Snmp`类提供了多种方法,如`get`, `set`, `trap`等,以执行SNMP操作。这些方法通常与`CommunityTarget`对象一起使用,来...

    SNMP4J 的jar包

    `snmp4j-agent-2.0.10a.jar`则是SNMP4J的代理扩展,它提供了构建SNMP代理所需的功能,如MIB对象的管理、变量绑定(Variable Binding)处理、陷阱(Trap)发送等。MIB(Management Information Base)是定义网络设备...

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

    它基于TCP/IP协议栈,通过发送GET和SET请求来获取或修改网络设备的管理对象。 SNMP4j库为Java开发者提供了一个完整的SNMP解决方案,包括PDU(协议数据单元)的构建、编码、解码以及错误处理等功能。使用SNMP4j,你...

    snmp.zip_SNMP4J MIB_java mib_mib_mib snmp4j_snmp模拟

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

    snmp4j文档

    **SNMP4J文档概述** SNMP4J是一个开源的Java实现,用于支持简单网络管理协议(SNMP)的应用程序开发。它提供了完整的SNMPv1、SNMPv...通过深入理解和实践文档中的内容,你可以熟练地运用SNMP4J来监控和控制网络环境。

    SNMP4J最新API

    这个最新的API版本包括了`snmp4j-2.0.3.jar`,`snmp4j-2.0.3-javadoc.jar`以及`snmp4j-agent-2.0.5.jar`这三个组件,它们各自扮演着不同的角色。 1. **snmp4j-2.0.3.jar**: 这是SNMP4J的主要库文件,包含了SNMP协议...

    SNMP4j帮助文件

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

    snmp4j-2.3.0源码等

    SNMP4J支持多种传输层协议,如UDP(默认)和TCP,通过不同的TransportMapping实现。 4. **Security Models**: 对于SNMP v3,SNMP4J实现了USM、V1/2 Community-Based Security和Vacm Access Control Model。 5. ...

    snmp4j 开发包

    3. **PDU(Protocol Data Unit)操作**:SNMP4J提供了Get、Set、Trap等基本PDU操作,用于读取、修改网络设备状态或发送陷阱通知。 4. **事件处理**:SNMP4J的事件驱动模型允许开发者注册监听器以响应来自网络的SNMP...

    snmp4j-2.0.3.zip_snmp4j 2.0.3

    1. **全面的SNMP支持**:SNMP4J不仅支持SNMP的基本操作,如GET、SET、TRAP,还支持非确认模式、同步和异步请求,以及SNMPv3的安全模型,包括用户安全模块(USM)、访问控制模型(ACM)和认证与加密机制。 2. **易于...

    snmp4j源码

    8. **异步编程模型**:SNMP4J提供了异步请求处理机制,允许开发者在一个非阻塞模式下发送SNMP请求,提高程序性能。相关的类如`AsyncRequest`和`FutureResponse`用于异步操作。 9. **错误处理和异常**:在源码中,...

    snmp4j文档 提供了对snmp的封装

    SNMP4J是一个Java库,专门用于实现简单网络管理协议(SNMP)的应用程序。SNMP是一种广泛应用于网络设备管理的标准协议,它允许系统管理员监控和管理网络中的硬件、软件和网络服务。SNMP4J提供了对SNMPv1、SNMPv2c和...

    snmp4j最新开发包

    SNMP4J是一个Java实现的简单网络管理协议(SNMP)的应用编程接口(API),它为开发者提供了在Java环境中开发SNMP应用的功能。这个最新的2.3.1版本是官方发布的,确保了稳定性和兼容性。下面将详细介绍SNMP4J的几个...

    snmp4j

    2. **事件驱动模型**: SNMP4J基于事件驱动的设计模式,允许应用程序订阅并处理SNMP响应和陷阱事件。 3. **灵活的PDU处理**: 支持所有类型的SNMP协议数据单元(PDU),包括Get, Set, GetNext, GetBulk等操作,以及 ...

Global site tag (gtag.js) - Google Analytics