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

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.jar

    snmp4j,官方默认会把中文字符转成16进制,通过修改源码方式,修复了次问题,此包可以直接支持trap里的中文显示。

    使用snmp4j实现Snmp功能.pdf

    使用java简单地实现snmp的功能 连接到的设备是自己windows,端口号为161,通过windows 的snmp协议实现了对设备systemName的修改和查询

    jjava日志文件log4j

    而且,通过使用各种第三方扩展,您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。  说明:下面分为三部分,  第一部分讲解如何配置log4j;  第二部分为对log4j.properties配置文件中的各个属性的讲解; ...

    log4j.properties

    Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套...而且,通过使用各种第三方扩展,您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。

    使用Log4j进行日志操作

    而且,通过使用各种第三方扩展,您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。 本文介绍的Log4j版本是1.2.3。作者试图通过一个简单的客户/服务器Java程序例子对比使用与不使用Log4j 1.2.3的差别,并详细...

    日志管理Log4j学习笔记

    Log4j 是 Apache 的一个开放源代码项目,通过使用 Log4j ,我们可以控制日志信 送的目的地是控制台、文件、 GUI 组件、甚至是套接口服务器、 NT 的事件记录器、 X Syslog 守护进程等;我们也可以控制每一条日志的...

    Apache的一个开放源代码的项目log4j

    log4j是Apache的一个开放源代码的项目,通过使用log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是...而且,通过使用各种第三方扩展,您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。

    nstat命令 监视内核的SNMP计数器和网络接口状态

    nstat是一个简单的监视内核的SNMP计数器和网络接口状态的实用工具 。 语法格式:nstat [参数] 常用参数: -z 显示0计数器 -h 显示帮助信息 -V 显示指令版本信息 -r 清零历史统计 -n 不显示任何内容,仅...

    Apache log4jf详细用法说明

    在强调可重用组件开发的今天,除了自己从头到尾开发一个可重用的日志操作类外,Apache为我们提供了一个强有力的日志操作包-...而且,通过使用各种第三方扩展,您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。

    javasnmp源码-shentou:shentou

    snmp 源码 Team:Syclover Author:L3m0n Email: [TOC] ###域环境搭建 准备: DC: win2008 DM: win2003 DM: winxp win2008(域控) 1、修改计算机名: 2、配置固定ip: 其中网关设置错误,应该为192.168.206.2,开始默认...

    java开源包4

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包1

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包11

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包2

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包3

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包6

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包5

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包10

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

    java开源包8

    BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...

Global site tag (gtag.js) - Google Analytics