mina IoBuffer 处理断包、粘包




  今天下午重温了一下项目中消息处理部分,其中关于IoBuffer重新学习了一下。

  版本mina1.7.;

  IoBuffer中有三个重要的方法,limit capacity position.

  其中capacity >= limit >= position >= 0;

  在mina1.7版本中IoBuffer还不支持自动增长,所以在接收数据的时候,必须手动扩展其容量。

  private DEFAULT_CAPACITY = 64;

private IoBuffer buffer = IoBuffer.allocate(DEFAULT_CAPACITY);

private void decode(IoBuffer in) {
 put(in); // 添加新数据 
}


private void put(IoBuffer in) {
   // 将要添加的数据超过预定义的容量大小
   if (in.remaining > buffer.remaining()) {
      // 扩大空间的1.5倍
      expend((buffer.position() + in.remianing)) * 3 / 2);       
   }
}

private void expend(int capacity) {
  IoBuffer newBuffer = IoBuffer.allocate(capacity);
  buffer.flip();
  newBuffer.put(buffer);
  buffer = newBuffer;
}

  这样我们就实现了IoBuffer的空间扩展。

  

  在接收客户端数据的时候,有三种情况出现:1)正常数据包 2)断包,也就是数据不全 3)粘包,多个包数据情况

 

  在正常数据包的情况下,我们正常处理即可。

  在断包时,我们就要保存上一次发送过来的数据,以便在下一次数据过来时,可以连接的上。

  

  例如:将2个Buffer数据合为1个

  IoBuffer totalData = IoBuffer.allocate(20);
  IoBuffer buf1 = IoBuffer.allocate(8);
  IoBuffer buf2 = IoBuffer.allocate(8);
  完整数据为1、2、3、4;
  buf1.putInt(1);
  buf1.putInt(2);
  buf1.flip();
  totalData.put(buf1.buf()); // 这样我们将buf1中的数据存放到了totalData中。但是并不是完整的数据,所以我们还需要再接收buf2的数据。
  totalData.flip();
  在读取数据之前,我们记下totalData的limit
  int limit = totalData.limit();
  先读出2个数据。totalData.getInt();totalData.getInt();
  此时totalData.position() 为8;totalData.limit()为8;
  因为数据不完整,所以在有数据过来时,我们要从position = 8这个位置开始读取新的数据。
  所以我们这是position的起点为刚开始记录的limit
  totalData.position(limit); 这样再数据过来时,就从limit位置开始存储新数据
 
  totalData.put(buf2.buf());
  totalData.flip(); 这样就把buf1和buf2的数据全部都合并起来了,也就是我们处理断包和粘包时候的操作。


 

  这里只是写了一个啰嗦繁琐的实例,让过程看的更清晰,真实世界中,我们会在循环不断的去读取数据。


你可能感兴趣的:(mina框架)