Package com.yz.net.impl

Source Code of com.yz.net.impl.IoSessionImpl

package com.yz.net.impl;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.List;
import java.util.Queue;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

import com.yz.net.ClosedSessionException;
import com.yz.net.CloseingSessionException;
import com.yz.net.IoFuture;
import com.yz.net.IoSession;
import com.yz.net.NetMessage;

/**
* <p>
* IO会话实现类
* </p>
* <br>
* @author 胡玮@ritsky
*
*/
public class IoSessionImpl implements IoSession{
 
  /**sessionId*/
  private long id;
 
  /**属性映射表*/
  private HashMap<String, Object> attributeMap = new HashMap<String, Object>();
 
  /**是否正式被关闭*/
  private volatile boolean isClose;
 
  /**是否正在关闭中*/
  AtomicBoolean isCloseing = new AtomicBoolean(false);
 
  /**是否正在改变控制*/
  AtomicBoolean isChangeingControl = new AtomicBoolean(false);
 
 
  /**是否正在超时处理中超时处理中,false:还未开始超时处理,true:超时处理开始了*/
  AtomicBoolean isOverTimeHandleing = new AtomicBoolean(false);
 
  /**通道*/
  private SocketChannel channel;
 
  /**选择键*/
  private SelectionKey selectionKey;
 
  /**写消息时,是否为阻塞写*//*
  private boolean isblockWrite;
 
  *//**读消息时,是否阻塞读*//*
  private boolean isblockRead;
 
  *//**关闭会话时,是否阻塞关闭*//*
  private boolean isblockClose;*/
 
  /**最近读时间*/
  long lastReadTime = System.currentTimeMillis();
 
  /**最近写时间*/
  long lastWriteTime = System.currentTimeMillis();
 
  /**最近访问时间*/
  long lastAccessTime = System.currentTimeMillis();
 
  /**写队列*/
  private ConcurrentLinkedQueue<IoFuture> writeQueue = new ConcurrentLinkedQueue();
 
  /**IoSession在哪个地方注册的*/
  private IoReadWriteMachine ownerDispatcher;
 
  /**IoSession的归属接收器*/
  private AbstractIoService ownerAcceptor;
 
  /**输入buffer*/
  private ByteBuffer inBuffer;
 
  /**检查超时*/
  private OverTimeCheckTask checkOverTime;
 
  /**关闭会话时的Future*/
  private CloseFuture closeFuture = new CloseFuture(this);
 
  //TODO:考虑加入到目前为止,总共接收了多少数据,按字节计算
 
  IoSessionImpl() {
    checkOverTime = new OverTimeCheckTask();
  }
 
  protected IoSessionImpl(SocketChannel channel, IoReadWriteMachine dispatcher) {
    this.channel = channel;
    this.ownerDispatcher = dispatcher;
    checkOverTime = new OverTimeCheckTask();
    //this.inBuffer = this.ownerDispatcher.getMemoryManager().allocat(10240);        //分配10的输入cache
  }
 
 
  protected IoSessionImpl(long id, SocketChannel channel, AbstractIoService acceptor) {
    this.id = id;
    this.channel = channel;
    this.ownerAcceptor = acceptor;
    checkOverTime = new OverTimeCheckTask();
  }
 
  CloseFuture getCloseFuture() {
    return closeFuture;
  }
 
 
  /**获得超时检查任务*/
  OverTimeCheckTask getCheckOverTime() {
    return checkOverTime;
  }
 
  /**获是通道*/
  protected SocketChannel getChannel() {
    return channel;
  }
 
  SelectionKey getSelectionKey(){
    return selectionKey;
  }
 
  void setSelectionKey(SelectionKey key) {
    this.selectionKey = key;
  }
 
  /**
   * 设置归属发报机
   * @param dispatcher
   */
  void setOwnerDispatcher(IoReadWriteMachine dispatcher) {
    this.ownerDispatcher = dispatcher;
  }
 
  /**
   * 分配输入buffer
   */
  void allocatInBuffer() {
    //TODO:
    //TODO:完善内存管理后,输入buffer从内存管理中获得
    //ByteBuffer buffer = this.ownerDispatcher.getMemoryManager().allocat();
    this.inBuffer = this.ownerDispatcher.getMemoryManager().allocat();
   
    //TODO:测试打印
    System.out.println("AllocatThreadName = " + this.ownerDispatcher.threadName);
//    System.out.println("AllocatNum = " + this.ownerDispatcher.getMemoryManager().getBufferNum());
   
    //this.inBuffer = ByteBuffer.allocateDirect(1024 * 5);
   
  }
 
 
  protected AbstractIoService getOwnerAcceptor() {
    return ownerAcceptor;
  }
 
 
  @Override
  public void addAttribute(String key, Object obj) {
    synchronized (attributeMap) {
      attributeMap.put(key, obj);
    }
  }

  @Override
  public int available() {
    throw new java.lang.UnsupportedOperationException("还没有实现");
  }

 
  @Override //关闭会话,关闭会话是异步关闭,如果需要同步,调用IoFuture上的wait
  public IoFuture close() {
    //TODO:测度代码
    System.out.println("IoSession-" + id + "-Close");
   
    if(this.isCloseing.compareAndSet(false, true)) {
      if(this.closeFuture == null) {
        closeFuture = new CloseFuture(this);
      }
     
      this.writeQueue.offer(closeFuture);
     
      //已经进入关闭会话的流程,此时是不允许接收任何来自网络的数据了,所以要关闭读的监听
      this.setReadControl(false);
     
      //IO会话加入排程控制
      ownerDispatcher.scheduleControl(this);
   
    }
    return this.closeFuture;
  }

 
  /**在发报机中调用的立即关闭,调用会检查关闭是否在进行中*/
  void closeNow() throws IOException {
    if(this.isCloseing.get()) {
      closeNow0();
      this.isClose = true;   
    }
  }
 
 
  @Override
  public Object getAttribute(String key) {
    synchronized (attributeMap) {
      return attributeMap.get(key);
    }
  }

  @Override
  public long getId() {
    return id;
  }

  @Override /**是否正式关闭*/
  public boolean isClose() {
    return isClose;
  }
 
 
  /**是否正在半闭中*/
  public boolean isCloseing() {
    return isCloseing.get();
  }
 

  /**马上从网络读取消息*/
  void readNow() throws IOException {
    int readlen = this.channel.read(this.inBuffer);
   
    if(readlen == -1) {  //到达流末
      throw new IOException("End_Stream");
    }
   
    if(readlen > 0) {
     
      //当没有设置协议处者时
      if(ownerAcceptor.getConfigure().getProtocolHandler() == null) {  
        inBuffer.flip();
        byte[] msgdata = new byte[inBuffer.remaining()];
        inBuffer.get(msgdata);
        inBuffer.clear();
        ownerAcceptor.getConfigure().getIoHandler().messageReceived(this, msgdata);
      }
      else //当设置了协议处理者时
        ByteBuffer readBuf = inBuffer.asReadOnlyBuffer();
        readBuf.flip();

        List<NetMessage> list = ownerAcceptor.getConfigure().getProtocolHandler().onData(readBuf, this);

        //TODO:如果得到错误消息,应该立即终止读取,并关闭Session
       
       
        int size = list.size();
        if(list != null && size > 0) {
          inBuffer.position(readBuf.position());
          inBuffer.limit(readBuf.limit());

          inBuffer.compact();                  //压缩,把剩余的字节放到inBuffer的最前面
          inBuffer.limit(inBuffer.capacity());

          //处理消息
          for(int i=0; i<size; i++) {
            NetMessage msg = list.get(i);
            if(msg.equals(NetMessage.ERROR_MSG)) {  //协议解析发生不可恢复错误
              this.close();     //发出关闭请求
              return;      //发生错误后,不能下文处理了.
            }
            else {
              this.ownerAcceptor.getConfigure().getIoHandler().messageReceived(this, msg);
            }
          }
        }
      }
    }
  }
 
 
 
  void closeNow0() throws IOException {
    //TODO:测试代码
    System.out.println("IoSession-" + id + "-CloseNow");
   
    if(this.selectionKey != null) {
      this.selectionKey.cancel();
    }
   
    if(channel != null) {
      channel.close();
      channel.socket().close();
    }
   
    try {
      if(this.inBuffer != null) {
        this.ownerDispatcher.getMemoryManager().free(this.inBuffer);
      }
    }
    catch(Exception e) {}
   
    //this.isClose = true;   
  }
 
 
  @Override
  public NetMessage read() {
    throw new java.lang.UnsupportedOperationException("还没有实现");
  }

  @Override
  public void read(NetMessage[] msgs) {
    throw new java.lang.UnsupportedOperationException("还没有实现");
   
  }

  @Override
  public Object removeAttribute(String key) {
    synchronized (attributeMap) {
      return attributeMap.remove(key);
    }
  }

  @Override/**写消息*/
  public IoFuture write(NetMessage msg) {
    if(msg == null) {
      throw new IllegalArgumentException("msg is null");
    }
   
    WriteFuture future = new WriteFuture(this, ByteBuffer.wrap(msg.getContent()));
   
    //会话已经被关闭了
    if(isClose) {
      future.setComplete(new ClosedSessionException("会话已经被关闭了...."));
      return future;
    }
   
    if(!this.isCloseing.get()) {
      this.writeQueue.offer(future);
     
      /*//判断协议处理者的要求是否为写完后关闭
      if(this.ownerAcceptor.getProtocolHandler().isClose()) {
        this.close();
      }*/
   
      //IO会话加入排程控制
      ownerDispatcher.scheduleControl(this);
   
      //ownerDispatcher.wakeup();
    }
    else {
      future.setComplete(new CloseingSessionException("会话正处于正在关闭状态中...."));
    }
   
    return future;
  }

 
 
 
  /**获得写队列*/
  protected Queue<IoFuture> getWriteQueue() {
    return this.writeQueue;
  }
 
  /**
   * <p>
   * 设置写控制
   * </p>
   * <br>
   * @param isopen 是否打开写
   */
  void setWriteControl(boolean isopen) {
    if(!selectionKey.isValid()) {
      return;
    }
   
    int op = this.selectionKey.interestOps();
    if(isopen) {
      op = op | SelectionKey.OP_WRITE;
    }
    else {
      op = op ^ SelectionKey.OP_WRITE;
    }
    this.selectionKey.interestOps(op);
  }
 
 
  /**
   * <p>
   * 设置读控制
   * </p>
   * <br>
   * @param isopen 是否打开读
   */
  void setReadControl(boolean isopen) {
    if(!selectionKey.isValid()) {
      return;
    }
   
    int op = this.selectionKey.interestOps();
    if(isopen) {
      op = op | SelectionKey.OP_READ;
    }
    else {
      op = op ^ SelectionKey.OP_READ;
    }
    this.selectionKey.interestOps(op);
  }

 
  void setConnectControl(boolean isopen) {
    if(!selectionKey.isValid()) {
      return;
    }
   
    int op = this.selectionKey.interestOps();
    if(isopen) {
      op = op | SelectionKey.OP_CONNECT;
    }
    else {
      op = op ^ SelectionKey.OP_CONNECT;
    }
    this.selectionKey.interestOps(op);
  }
 
 
  /**通知超时了*/
  void notifyOverTime() {
    long currTime = System.currentTimeMillis();
   
    long bathOverTime = ownerAcceptor.getConfigure().getBothOverTime();
   
    if(bathOverTime > 0) {
      if((currTime - lastAccessTime) > bathOverTime) {
        if(isOverTimeHandleing.get()) {
          //都超时了
          this.ownerAcceptor.getConfigure().getOverTimeHandler().onBothOverTime(this);
        }
        isOverTimeHandleing.set(false);
        return;
      }
    }
   
    long readOverTime = ownerAcceptor.getConfigure().getReadOverTime();
   
    if(readOverTime > 0) {
      if((currTime - this.lastReadTime) > readOverTime) {
        if(isOverTimeHandleing.get()) {
        //都超时了
          this.ownerAcceptor.getConfigure().getOverTimeHandler().onReadOverTime(this);
        }
      }
    }
   
    long writeOverTime = ownerAcceptor.getConfigure().getWriteOverTime();
   
    if(writeOverTime > 0) {
      if((currTime - this.lastWriteTime) > writeOverTime) {
        if(isOverTimeHandleing.get()) {
          //都超时了
          this.ownerAcceptor.getConfigure().getOverTimeHandler().onWriterOverTime(this);

        }
      }
    }
    isOverTimeHandleing.set(false);
  }
 
 
 
  /**定时检查是否超时*/
  private class OverTimeCheckTask extends TimerTask {

    @Override
    public void run() {
     
     
     
      long currTime = System.currentTimeMillis();
      long bothOverTime = ownerAcceptor.getConfigure().getBothOverTime();
      long readOverTime = ownerAcceptor.getConfigure().getReadOverTime();
      long writeOverTime = ownerAcceptor.getConfigure().getWriteOverTime();
     
      if(bothOverTime <=0 || readOverTime <= 0 || writeOverTime <=0 ) {
        //TODO:不存在超时处理
        return;
      }
     
     
      //检查是否有超时产生,有的话就排序到IO处理线程中去
      if((currTime - lastAccessTime) > bothOverTime ||
          (currTime - lastReadTime) > readOverTime ||
          (currTime - lastWriteTime) > writeOverTime) {
        if(!IoSessionImpl.this.isCloseing() || !IoSessionImpl.this.isClose()) {
          if(isOverTimeHandleing.compareAndSet(false, true)) {
            ownerDispatcher.scheduleOverTime(IoSessionImpl.this); //排程 
          }
        }
      }
    }
   
  }



  @Override
  public IoFuture connect() {
    throw new java.lang.UnsupportedOperationException("不能进行操作....");
  }
}
TOP

Related Classes of com.yz.net.impl.IoSessionImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.