SNMP4J源码主要类解析

Posted 哦啦哦啦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SNMP4J源码主要类解析相关的知识,希望对你有一定的参考价值。

主要几个类

org.snmp4j.Snmp

这是最主要的一个类,无论实现设备监听器还是发送接收设备报文,都需要先创建这个对象。有listen(),get(),send()等方法

org.snmp4j.TransportMapping

TransportMapping接口代表了SNMP4J所使用的传输层协议。这也是SNMP4J一大特色之一。按照RFC规定,SNMP只使用UDP作为传输层协议。而SNMP4J支持管理端和代理端使用UDP或TCP进行传输。

如果要添加自己的传输协议,继承此接口。

org.snmp4j.PDU

PDU类是SNMP报文单元的抽象,其中PDU类适用于SNMPv1和SNMPv2c。ScopedPDU类继承自PDU类,适用于SNMPv31。

org.snmp4j.CommunityTarget

CommunityTarget类实现了Target接口,用于SNMPv1和SNMPv2c这两个版本。UserTarget类实现了Target接口,适用于SNMPv31。
除了提供由Target接口定义的地址、重传和超时策略信息外,还提供community信息(可以理解为通信密钥)。

org.snmp4j.CommandResponder

监听器接口,接口只有一个processPdu方法,用来处理收到的报文。

org.snmp4j.MessageDispatcher

MessageDispatcherImpl 使用 MessageProcessingModel 实例解码和分派传入消息,并使用适当的 TransportMapping 实例对传出消息进行编码和发送。方法processMessage将从TransportMapping调用,而方法sendPdu将由应用程序调用。

常见用法

发送SNMP请求和构造监听器代码前四行是一致的,都是构造SNMP对象,然后开启监听。SNMP send调用的是java.net.DatagramSocket的send方法,监听器调用的是DatagramSocket的receive方法

发送SNMP请求伪代码步骤:

// 初始化消息分发器,这里举例常用的多线程消息分发器
new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl());
// 初始化TransportMapping对象,这里举例常用的udp,参数为目标地址对象
new DefaultUdpTransportMapping(UdpAddress);
// 初始化snmp对象
new Snmp(MessageDispatcher, TransportMapping);
// 设置监听模式,以启动Transport Mappings的内部监听线程。
snmp.listen();
// 初始化pdu和CommunityTarget对象并调用snmp对象的send方法
snmp.send(pdu, CommunityTarget);

构造监听器伪代码步骤:

// 初始化消息分发器,这里举例常用的多线程消息分发器
new MultiThreadedMessageDispatcher(threadPool, new MessageDispatcherImpl());
// 初始化TransportMapping对象,这里举例常用的udp,参数为目标地址对象
new DefaultUdpTransportMapping(UdpAddress);
// 初始化snmp对象
new Snmp(MessageDispatcher, TransportMapping);
// 设置监听模式,以启动Transport Mappings的内部监听线程。
snmp.listen();
// 添加自定义的监听器(实现CommandResponder接口,并重写processPdu方法)
snmp.addCommandResponder(自定义监听类);
// 接收到的消息在processPdu方法处理

Netty4:源码解析ObjectDecoder和ObjectEncoder两个类

1.声明

当前内容主要用于本人学习和了解netty中的ObjectDecoder和ObjectEncoder这两个类,明白其主要原理和主要操作

原因:之前使用ObjectDecoder传递对象的时候出现了一个问题,无法传递消息,无法接收消息,碰到了坑,所以要了解!

2.ObjectDecoder源码解析

直接找到解码方法

@Override
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception 
    ByteBuf frame = (ByteBuf) super.decode(ctx, in);
    if (frame == null) 
        return null;
    

    ObjectInputStream ois = new CompactObjectInputStream(new ByteBufInputStream(frame, true), classResolver);
    try 
        return ois.readObject();
     finally 
        ois.close();
    

发现主要实现:基于ByteBuf实现,通过解析流为对象流方式得到解码后的Object

采用调试方式查看:

这里明白了,为什么不能调用ReferenceCountUtil.release(msg);,之前有过这个错误!

继续:

结果得到一个标准的序列化对象输入流,解析为对象的(这就是为什么需要实现序列化接口的要求!)

最后就是标准的readObject方法

3.ObjectEncoder源码解析

直接查看加码方法

  @Override
protected void encode(ChannelHandlerContext ctx, Serializable msg, ByteBuf out) throws Exception 
    int startIdx = out.writerIndex();

    ByteBufOutputStream bout = new ByteBufOutputStream(out);
    ObjectOutputStream oout = null;
    try 
        bout.write(LENGTH_PLACEHOLDER);
        oout = new CompactObjectOutputStream(bout);
        oout.writeObject(msg);
        oout.flush();
     finally 
        if (oout != null) 
            oout.close();
         else 
            bout.close();
        
    

    int endIdx = out.writerIndex();

    out.setInt(startIdx, endIdx - startIdx - 4);

发现传递的为实现序列化的msg,并且采用ObjectOutputStream直接写出对象到ByteBuf中,(所以传输的对象必须实现序列化接口,其中会自动释放掉ByteBuf(父类中实现了))

4.总结

1.使用ObjectDecoder和ObjectEncoder不要手动释放msg,并且传递的对象都是需要实现序列化接口的,否则任何一点出现问题,那么程序就会出现无法接收消息和无法传递消息的问题!

以上是关于SNMP4J源码主要类解析的主要内容,如果未能解决你的问题,请参考以下文章

iOS网络——AFNetworking AFURLSessionManager源码解析

iOS网络——SDWebImage SDImageDownloader源码解析

iOS网络——AFNetworking AFURLSessionManager源码解析

iOS网络——AFNetworking AFHttpSessionManager源码解析

iOS网络——SDWebImage SDImageDownloader源码解析

iOS网络——AFNetworking AFHttpSessionManager源码解析