All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.voovan.network.IoSession Maven / Gradle / Ivy

There is a newer version: 4.3.8
Show newest version
package org.voovan.network;

import org.voovan.network.exception.ReadMessageException;
import org.voovan.network.exception.SendMessageException;
import org.voovan.tools.ByteBufferChannel;
import org.voovan.tools.TByteBuffer;
import org.voovan.tools.TEnv;
import org.voovan.tools.TObject;
import org.voovan.tools.log.Logger;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 会话抽象类
 * 
 * @author helyho
 *
 * Voovan Framework.
 * WebSite: https://github.com/helyho/Voovan
 * Licence: Apache v2 License
 */
public abstract class IoSession {
	
	private Map attributes;
	private SSLParser sslParser;

	private boolean receiving;
	private MessageLoader messageLoader;
	private ByteBufferChannel byteBufferChannel;
	private T socketContext;

	/**
	 * 构造函数
	 * @param socketContext socketContext对象
	 */
	public IoSession(T socketContext){
		attributes = new ConcurrentHashMap();
		this.socketContext = socketContext;
		byteBufferChannel = new ByteBufferChannel(socketContext.getBufferSize());
		messageLoader = new MessageLoader(this);
	}

	protected boolean isReceiving() {
		return receiving;
	}

	protected void setReceiving(boolean receiving) {
		this.receiving = receiving;
	}

	/**
	 * 获取接收的输出流
	 *
	 * @return 接收的输出流
	 */
	public ByteBufferChannel getByteBufferChannel() {
			return byteBufferChannel;
	}

	/**
	 * 获取 SSLParser
	 * @return SSLParser对象
	 */
	public SSLParser getSSLParser() {
		return sslParser;
	}
	
	/**
	 * 获取 SSLParser
	 * @param sslParser SSL解析对象
	 */
	protected void setSSLParser(SSLParser sslParser) {
		if(this.sslParser==null){
			this.sslParser = sslParser;
		}
	}

	/**
	 * 获取会话参数
	 * @param key 参数名
	 * @return    参数对象
	 */
	public Object getAttribute(Object key) {
		return attributes.get(key);
	}

	/**
	 * 设置会话参数
	 * @param key     参数名
	 * @param value   参数对象
	 */
	public void setAttribute(Object key, Object value) {
		this.attributes.put(key, value);
	}

	/**
	 * 移除会话参数
	 * @param key     参数名
	 */
	public void removeAttribute(Object key) {
		this.attributes.remove(key);
	}
	
	/**
	 * 检查会话参数是否存在
	 * @param key     参数名
	 * @return 是否包含
	 */
	public boolean containAttribute(Object key) {
		return this.attributes.containsKey(key);
	}

	/**
	 * 获取本地 IP 地址
	 * @return	本地 IP 地址
	 */
	public abstract String loaclAddress();
	
	/**
	 * 获取本地端口
	 * @return 返回-1为没有取到本地端口
	 */
	public abstract int loaclPort();
	
	/**
	 * 获取对端 IP 地址
	 * @return  对端 ip 地址
	 */
	public abstract String remoteAddress();
	
	/**
	 * 获取对端端口
	 * @return 	返回-1为没有取到对端端口
	 */
	public abstract int remotePort();
	
	/**
	 * 获取 socket 连接上下文
	 * @return	socket 连接上下文, 连接断开时返回的是null
	 */
	public T socketContext() {
		return socketContext;
	};
	
	/**
	 * 读取消息到缓冲区
	 * @param buffer    接收数据的缓冲区
	 * @return 接收数据大小
	 * @throws IOException IO 异常
	 */
	protected abstract int read0(ByteBuffer buffer) throws IOException;

	
	/**
	 * 发送消息
	 * 		注意直接调用不会出发 onSent 事件
	 * @param buffer  发送缓冲区
	 * @return 读取的字节数
	 * @throws IOException IO 异常
	 */
	protected abstract int send0(ByteBuffer buffer) throws IOException;

	/**
	 * 同步读取消息
	 * 			消息会经过 filter 的 decoder 函数处理后再返回
	 * @return 读取出的对象
	 * @throws ReadMessageException  读取消息异常
	 */
	public Object syncRead() throws ReadMessageException {
		Object readObject = null;
		while(true){
			readObject = getAttribute("SocketResponse");
			if(readObject!=null){
				removeAttribute("SocketResponse");
				break;
			}else {
				Exception exception = TObject.cast(getAttribute("SocketException"));
				if (exception != null) {
					removeAttribute("SocketException");
					throw new ReadMessageException("Method syncRead error! Error by " +
							exception.getClass().getSimpleName() + ". " + exception.getMessage(), exception);
				}
			}

			if(!isConnected()){
				break;
			}
			TEnv.sleep(1);
		}

		return readObject;
	}

	/**
	 * 同步发送消息
	 * 			消息会经过 filter 的 encoder 函数处理后再发送
	 * @param obj  要发送的对象
	 * @throws SendMessageException  消息发送异常
	 */
	public void syncSend(Object obj) throws SendMessageException{
		//等待 ssl 握手完成
		while(sslParser!=null && !sslParser.handShakeDone){
			TEnv.sleep(1);
		}

		if (obj != null) {
			try {
				obj = EventProcess.filterEncoder(this,obj);

				EventProcess.sendMessage(this, obj);
			}catch (Exception e){
				throw new SendMessageException("Method syncSend error! Error by "+
						e.getClass().getSimpleName() + ".",e);
			}
		}
	}



	/**
	 * 设置是否使用分割器读取
	 * @param useSpliter true 使用分割器读取,false 不使用分割器读取,且不会出发 onRecive 事件
	 */
	public void enabledMessageSpliter(boolean useSpliter) {
		messageLoader.setUseSpliter(useSpliter);
	}


	/**
	 * 发送SSL消息
	 * 		注意直接调用不会出发 onSent 事件
	 * 	@param buffer byte缓冲区
	 * 	@return 发送的数据大小
	 */
	public int send(ByteBuffer buffer){
        try {
            if(sslParser!=null && sslParser.isHandShakeDone()) {
                sslParser.warpData(buffer);
                return buffer.limit();
            }else{
                return send0(buffer);
            }
        } catch (IOException e) {
            Logger.error("Send data failed." + e.getMessage(),e);
        }

		return -1;
	}

	/**
	 * 直接从缓冲区读取数据
	 * @param byteBuffer 字节缓冲对象ByteBuffer,读取 前需要使用 enabledMessageSpliter(false) 停止分割器的工作,除非有特殊的需求.
	 * @return  读取的字节数
	 * @throws IOException IO异常
	 * */
	public int read(ByteBuffer byteBuffer) throws IOException {

		int readSize = -1;

		readSize = this.read0(byteBuffer);

		if(!this.isConnected() && readSize <= 0){
			readSize = -1;
		}

		return readSize;
	}

	/**
	 * 获取消息处理类
	 * @return 消息处理类
	 */
	public MessageLoader getMessageLoader() {
		return messageLoader;
	}

	/**
	 * 获取消息分割处理类
	 * @return 消息分割处理类
	 */
	protected abstract MessageSplitter getMessagePartition();
	
	/**
	 * 会话是否连接
	 * @return	true: 连接,false: 关闭
	 */
	public abstract boolean isConnected();

	/**
	 * 会话是否打开
	 * @return	true: 打开,false: 关闭
	 */
	public abstract boolean isOpen();
	
	/**
	 * 关闭会话
	 * @return 是否关闭
	 */
	public abstract boolean close();
	
	@Override
	public abstract String toString();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy