java flash tcp字节流通信(四)-java 粘包/半包处理器(数据缓存)

来源:互联网 发布:js计算合计 编辑:程序博客网 时间:2024/05/28 16:03

package com.net.tcp;

import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/**
 *
 * TCP通信数据缓存(粘包/半包处理)
 *
 */
public class DataCache {
 /**数据包*/
 private List<DataPack> packs;
 private ByteBuffer cache;
 
 public DataCache(int capacity){
  packs = new ArrayList<DataPack>();
  cache = ByteBuffer.allocate(capacity);
 }
 
 /**
  * 读取字节流
  * @param channel
  * @return
  * @throws Exception
  */
 public int read(SocketChannel channel) throws Exception{
  int reads = 0;
  DataPack pack = null;
  pack = lastUnComplete(true);
  reads += readHead(channel, pack);
  if(pack.getHead().getLen() > 0){
   reads += readContent(channel, pack);
  }
  return reads;
 }
 
 /**
  * 将所有包发送
  * @param channel
  * @return
  * @throws Exception
  */
 public boolean write(SocketChannel channel) throws Exception{
  DataPack pack = null;
  boolean sign = true;
  Iterator<DataPack> it = packs.iterator();
  while(it.hasNext() && sign){
   pack = it.next();
   channel.write(pack.getHead().getContent());
   if(!pack.getHead().getContent().hasRemaining()){
    ByteBuffer buffer = pack.getContent().current(false);
    while(buffer != null){
     channel.write(buffer);
     if(buffer.hasRemaining()){
      sign = false;
      break;
     }
     buffer = pack.getContent().next(false);
    }
   }
  }
  return sign;
 }
 
 /**
  * 返回队头,被移除
  * @return
  */
 public DataPack poll(){
  if(packs.size() > 0){
   DataPack pack = packs.get(0);
   if(pack.isComplete(true)){
    packs.remove(0);
    return pack;
   }
  }
  return null;
 }
 
 public void push(DataPack pack){
  this.packs.add(pack);
 }
 
 /**
  * 读取包头
  * @param head
  * @param channel
  * @return
  * @throws Exception
  */
 private int readHead(SocketChannel channel, DataPack pack) throws Exception{
  int reads = 0;
  DataHead head = pack.getHead();
  if(head.getLen() == 0){
   reads = channel.read(head.getContent());
   if(pack.getHead().isComplete()){
    pack.getHead().init();
   }
  }
  return reads;
 }
 
 /**
  * 读取内容
  * @param channel
  * @param pack
  * @return
  * @throws Exception
  */
 private int readContent(SocketChannel channel, DataPack pack) throws Exception{
  DataContent content = pack.getContent();
  int reads = 0;
  boolean sign = false;
  while(!pack.isComplete(false)){
   reads += channel.read(cache);
   sign = cache.hasRemaining();
   cache.flip();
   content.put(cache);
   cache.clear();
   if(sign)
    break;
  }
  if(pack.isComplete(false)){
   pack.filp();
  }
  return reads;
 }
 
 /**
  * 返回最后一个包
  * @param create 传true当最后一个包为完整包时,创建一个新包
  * @return
  */
 public DataPack lastUnComplete(boolean create){
  DataPack pack = null;
  if(packs.size() > 0){
   pack = packs.get(packs.size() - 1);
   if(pack.isComplete(false) && create){
    pack = new DataPack();
    packs.add(pack);
   }
  }else{
   pack = new DataPack();
   packs.add(pack);
  }
  return pack;
  
 }
}

原创粉丝点击