首页 > OOP语言 > 其它 > 正文

使用 Apache MINA 2 开发网络应用
2012-03-28 00:00:00   来源:www.bianceng.cn   评论:0 点击:

暂时无描述信息

在 清单 6 中,encode 方法封装了编码的逻辑。由于 AbstractTetrisCommand的 toBytes已经完成了到字节数组的转换,encode 方法直接使用即可。首先写入消息主体字节数组的长度,再是字节数组本身,就完成了编码的过程。

与编码过程相比,解码过程要相对复杂一些。具体的实现如 清单 7 所示。

清单 7. 联机游戏示例应用中消息解码器 CommandDecoder

public class CommandDecoder extends CumulativeProtocolDecoder {

  protected boolean doDecode(IoSession session, IoBuffer in,
      ProtocolDecoderOutput out) throws Exception {
    if (in.prefixedDataAvailable(4, Constants.MAX_COMMAND_LENGTH)) {
      int length = in.getInt();
      byte[] bytes = new byte[length];
      in.get(bytes);
      int commandNameLength = Constants.COMMAND_NAME_LENGTH;
      byte[] cmdNameBytes = new byte[commandNameLength];
      System.arraycopy(bytes, 0, cmdNameBytes, 0, commandNameLength);
      String cmdName = StringUtils.trim(new String(cmdNameBytes));
      AbstractTetrisCommand command = TetrisCommandFactory
        .newCommand(cmdName);
      if (command != null) {
        byte[] cmdBodyBytes = new byte[length - commandNameLength];
        System.arraycopy(bytes, commandNameLength, cmdBodyBytes, 0,
          length - commandNameLength);
        command.bodyFromBytes(cmdBodyBytes);
        out.write(command);
      }
      return true;
    } else {
      return false;
    }
  }
}

在 清单 7 中可以看到,解码器 CommandDecoder 继承自 CumulativeProtocolDecoder。这是 Apache MINA 提供的一个帮助类,它会自动缓存所有已经接收到的数据,直到编码器认为可以开始进行编码。这样在实现自己的编码器的时候,就只需要考虑如何判断消息的边界即可。如果一条消息的后续数据还没有接收到,CumulativeProtocolDecoder会自动进行缓存。在之前提到过,解码过程的一个重要问题是判断消息的边界。对于固定长度的消息来说,只需要使用 Apache MINA 的 IoBuffer的 remaining方法来判断当前缓存中的字节数目,如果大于消息长度的话,就进行解码;对于使用固定长度消息头来指明消息主体的长度的情况,IoBuffer提供了 prefixedDataAvailable方法来满足这一需求。prefixedDataAvailable会检查当前缓存中是否有固定长度的消息头,并且由此消息头指定长度的消息主体是否已经全部在缓存中。如果这两个条件都满足的话,说明一条完整的消息已经接收到,可以进行解码了。解码的过程本身并不复杂,首先读取消息的类别名称,然后通过 TetrisCommandFactory.newCommand方法来生成一个该类消息的实例,接着通过该实例的 bodyFromBytes方法就可以从字节数组中恢复消息的内容,得到一个完整的消息对象。每次成功解码一个消息对象,需要调用 ProtocolDecoderOutput的 write把此消息对象往后传递。消息对象会通过过滤器链,最终达到 I/O 处理器,在 IoHandler.messageReceived中接收到此消息对象。如果当前缓存的数据不足以用来解码一条消息的话,doDecode只需要返回 false即可。接收到新的数据之后,doDecode会被再次调用。

过滤器链

过滤器只有在添加到过滤器链中的时候才起作用。过滤器链是过滤器的容器。过滤器链与 I/O 会话是一一对应的关系。org.apache.mina.core.filterchain.IoFilterChain是 Apache MINA 中过滤器链的接口,其中提供了一系列方法对其中包含的过滤器进行操作,包括查询、添加、删除和替换等。如 表 5 所示。

表 5. IoFilterChain 接口的方法

方法 说明
addFirst(String name, IoFilter filter) 将指定名称的过滤器添加到过滤器链的开头。
addLast(String name, IoFilter filter) 将指定名称的过滤器添加到过滤器链的末尾。
contains(String name) 判断过滤器链中是否包含指定名称的过滤器。
get(String name) 从过滤器链中获取指定名称的过滤器。
remove(String name) 从过滤器链中删除指定名称的过滤器。
replace(String name, IoFilter newFilter) 用过滤器 newFilter替换掉过滤器链中名为 name的过滤器。
getSession() 获取与过滤器链一一对应的 I/O 会话。

在介绍完 I/O 过滤器和过滤器链之后,下面介绍 I/O 处理器。

相关热词搜索:

上一篇:使用Blueprint Container规范构建OSGi应用程序
下一篇:结合使用 Apache Geronimo 和 Lift

分享到: 收藏