`

Active MQ5.7版在NIO模式下SSL通信的问题以及后续版本的解决

阅读更多

Active MQ 5.7版在NIO模式下SSL通信可能会出现BufferUnderFlowException异常。NIO模式下SSL通信的工作类为 org.apache.activemq.transport.nio.NIOSSLTransport,数据包传输格式为数据长度dataL +数据内容dataContent,所以基本的命令处理算法是这样的

    

1 //得到数据包长度
nextFrameSize = plain.getInt();

2//为命令分配buffer,总长度为数据包长度 + 4,4是nextFrameSize自身的长度
currentBuffer = ByteBuffer.allocate(nextFrameSize + 4); 

3 //从socket buffer中读取数据到命令buffer
  currentBuffer.putInt(nextFrameSize); // 放入数据包长度

// 如果从socket读取的数据小于当前命令buffer的可用长度,则将socket数据全部读取命令buffer中
       if (currentBuffer.remaining() >= plain.remaining()) {
            currentBuffer.put(plain);
       }

//如果从socket读取的数据大于当前命令buffer的可用长度,则只从socket读取当前命令buffer的可用长度,这样保证读取的数据只属于本命令的数据
	 else {
               byte[] fill = new byte[currentBuffer.remaining()];
               plain.get(fill);
              currentBuffer.put(fill);
         }
4 //处理从socket读取的命令        
//如果命令buffer还没有写满,则返回,等待下个数据包
     if (currentBuffer.hasRemaining()) {
            return;
     } else {      
          //消费数据
            nextFrameSize = -1;//当前命令已经读取完毕

 

以上是5.7版本的处理方式,看起来不错,但是有个致命的问题,就是在第一步,

1 //得到数据包长度

nextFrameSize = plain.getInt();

 

由于是NIO方式,socket读取的数据不一定完整,这里plain的数据可能不到4个字节,也就是不是一个Int类型,调用plain.getInt();可能会抛出BufferUnderFlowException

 

5.8版本对这个问题作了大幅度的处理,思路是这样的:

1 根据数据包长度来判断数据包是否读取完整,如果没有读完,继续读;如果读完了,则处理该数据包;

2 读取分为两种情况,第一次读取还是第n次读取:

3 如果是第一次读,则需要先读取数据包长度,根据数据包长度分配当前buffer大小,然后读取数据包的内容部分;

4 如果是n次读,则直到把当前buffer写满就可以;

5 在读取数据包长度的时候,要判断数据包是否包含完整的Int类型数据,就是数据包长度是否大于等于32

如果数据包长度小于32,与前面读取数据内容类似,则读取分为两种情况,第一次读取还是第n次读取:第一次读取需要为当前buffer分配4个字节,也就是32位,读取数据然后返回;第n次读取判断当前buffer是否写满,如果写满了就从从当前buffer中读取Int

6 读取了数据包长度后构造新的当前buffer,长度为数据内容长度+4,转到步骤4

 

这样就彻底解决了NIO模式下的问题,下面是5.8版本完整的处理读入数据的代码:

 

protected void  processCommand(ByteBuffer plain) throws Exception {
        if (nextFrameSize == -1) {
            if (plain.remaining() < Integer.SIZE) {
                if (currentBuffer == null) {
                    currentBuffer = ByteBuffer.allocate(4);
                }
       while (currentBuffer.hasRemaining() && plain.hasRemaining()) {                    
                currentBuffer.put(plain.get());
                }
              if (currentBuffer.hasRemaining()) {
                    return;
                } else {
                    currentBuffer.flip();
                    nextFrameSize = currentBuffer.getInt();
                }
            } else {
                if (currentBuffer != null) {
                    while (currentBuffer.hasRemaining()) {
                        currentBuffer.put(plain.get());
                    }
                    currentBuffer.flip();
                    nextFrameSize = currentBuffer.getInt();
                } else {
                    nextFrameSize = plain.getInt();
                }
            }
            if (wireFormat instanceof OpenWireFormat) {
long maxFrameSize = ((OpenWireFormat) wireFormat).getMaxFrameSize();
                if (nextFrameSize > maxFrameSize) {
throw new IOException("***);
                }
            }
            currentBuffer = ByteBuffer.allocate(nextFrameSize + 4);
            currentBuffer.putInt(nextFrameSize); 
        } else {
            if (currentBuffer.remaining() >= plain.remaining()) {
                currentBuffer.put(plain); 
            } else {
                byte[] fill = new byte[currentBuffer.remaining()] 
                plain.get(fill);
                currentBuffer.put(fill);
            }
            if (currentBuffer.hasRemaining()) {
                return;
            } else {
                currentBuffer.flip(); Object command = wireFormat.unmarshal(new DataInputStream(new NIOInputStream(currentBuffer)));
                doConsume((Command) command);
                nextFrameSize = -1;
                currentBuffer = null;
            }
        } 
    }

 

 

 

分享到:
评论

相关推荐

    MySQL 5.7 版本驱动包

    MySQL 5.7 版本驱动包是针对Java开发者用于连接MySQL数据库的重要组件,它遵循JDBC(Java Database Connectivity)规范,使得Java程序能够通过标准API与MySQL数据库进行交互。在Java应用程序中,我们通常使用MySQL ...

    JAVA NIO MINA2调用大宝CA密码安全套件实现国密SSL安全通道,1.0.1版本,含通信示例代码

    使用方法见:https://blog.csdn.net/upset_ming/article/details/96491058 1. 修改了前一版本中证书验证的bug,支持JDK8的高版本 2. 支持国密SSL双向认证 3. 将过期的国密证书替换为新证书

    java nio 通信服务器、客户端完整例子

    用java编写的nio通信的例子,nio是io编程的新版本,比io较流行。同时本例子是适用socket通信的。可以在此基础上,添加您的个人应用。本例子适用于:java通信的学习者,android平台通信的学习者。

    NIO实现客户端之间通信

    在Java编程领域,NIO(New Input/Output)是一种非阻塞I/O模型,它提供了比传统的IO模型更高效的数据处理方式。NIO的核心组件包括通道(Channels)...因此,在需要处理大量并发连接的场景下,NIO是一个理想的解决方案。

    socket通信NIO代理模式demo实例

    在"socket通信NIO代理模式demo实例"中,你可以找到具体的代码实现,包括`Server`端和`Client`端的逻辑,以及如何使用`Selector`进行事件监听。通过对这个示例的学习,你可以深入理解NIO在代理模式中的应用,并能灵活...

    默蓝网络通信测试工具(NIOSocket工具)支持TCP/IP和HTTP通信-网络通信开发人员必备

    总的来说,"默蓝网络通信测试工具(NIOSocket工具)"凭借其对TCP/IP和HTTP通信的支持,以及Java NIO Socket编程的优势,为网络通信开发人员提供了全面的测试解决方案,是进行网络通信开发和优化的得力助手。...

    基于JavaNIO的非阻塞通信的研究与实现

    - 非阻塞通信模式允许线程在没有数据可读或无法写入的情况下继续执行其他任务,而不会被阻塞。这种方式可以显著提高系统的并发处理能力。在Java NIO中,可以通过将通道设置为非阻塞模式来实现这一目标。 #### Java...

    Nio非阻塞socket通信demo

    在“Nio非阻塞socket通信demo”中,你可能会看到如何创建和配置这些组件,以及如何编写处理读写事件的回调函数。通过这个示例,你可以深入理解NIO在Socket通信中的工作原理,并学习如何在实际项目中应用。

    基于java NIO的socket通信demo

    在这个“基于java NIO的socket通信demo”中,我们将探讨如何使用NIO进行服务器和客户端的Socket通信,并解决通信过程中的字符集乱码问题。 首先,我们来看`NioServer.java`。这个文件中包含了一个基于NIO的服务器端...

    NIO通信框架

    NIO通信框架 网络 通信 类 收集的资料 java 可以使用

    Nio多线程CS收发信息问题(问题已经解决)

    本文将深入探讨在NIO环境下,如何实现多线程客户端和服务端的通信问题,以及该问题的解决方案。 首先,我们来理解NIO的核心组件。Selector是NIO中的关键角色,它可以监控多个通道(Channels)的事件,例如连接建立...

    Active MQ教程+配置

    大多数商业J2EE应用服务器都内置了自己的JMS Provider,但独立的商业解决方案,如IBM WebSphere MQ,在业界仍然占据主导地位。 #### 四、安装ActiveMQ 1. **下载**:访问[ActiveMQ官方网站]...

    基于 MINA 的 TLS/SSL NIO Socket 实现(二)

    在本篇博文中,我们将深入探讨如何利用Apache MINA库实现基于TLS/SSL的NIO(非阻塞I/O)Socket通信。MINA是一个高度可扩展的网络应用框架,广泛用于构建高性能、高并发的网络应用程序,如服务器端的TCP和UDP服务。...

    使用NIO方式完成简单的通信

    在Java编程中,NIO(New IO)是一种与传统IO不同的I/O模型,它提供了非阻塞的输入/输出操作,适用于高并发、大数据量的网络应用。本教程将介绍如何使用NIO来实现简单的通信,包括消息头和消息体的设计。 首先,我们...

    JAVA NIO 异步通信客户端

    10. **安全性与异常处理**: 考虑到网络通信的不可靠性,客户端需要适当地处理连接失败、数据传输错误以及安全问题,例如使用SSL/TLS协议进行加密通信。 在压缩包中的`JavaNioTamplateClient`可能是实现以上概念的一...

    Java NIO - The NIO Architecture

    在Java早期版本中,如Java 1.0中的`java.io`包提供的流操作,以及Java 1.1中引入的字符流(readers和writers),虽然功能强大,但随着时间的发展,这些传统的I/O机制逐渐暴露出不足之处。例如,它们主要针对单线程...

    JAVA NIO 异步通信模板服务端

    JAVA NIO(New IO)是Java 1.4版本引入的一个新特性,它为Java提供了非阻塞I/O操作的能力,极大地提升了Java处理I/O的能力,尤其在高并发的网络应用中表现出色。异步通信是指客户端发起请求后,服务器不需要立即返回...

    Java NIO非阻塞服务端与客户端相互通信

    - **中断与关闭**:在非阻塞模式下,我们需要处理线程中断以及通道关闭的情况,确保程序的健壮性。 7. **实际应用** - **NIO在高并发服务器中的应用**:例如Tomcat服务器、Netty框架等都利用了Java NIO的特性来...

    基于Java NIO反应器模式设计与实现

    文中提到的Mina和Netty是使用Java NIO开发的高性能的网络通信框架。Mina是一个完全由Java编写的NIO框架,而Netty则是由JBOSS提供的一个高性能的异步事件驱动的网络应用框架,它们都是基于Java反应器模式设计的,用于...

Global site tag (gtag.js) - Google Analytics