您的位置:首页 > 其它

SNMP 修改SNMP4J消息内容

2014-11-13 16:11 190 查看
我记得上次就有人说我这种做法

 

上次是因为我要在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)

下载次数: 17
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: