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

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

package org.voovan.network;

import org.voovan.network.messagesplitter.TransferSplitter;
import org.voovan.network.udp.UdpSocket;
import org.voovan.tools.buffer.ByteBufferChannel;
import org.voovan.tools.exception.MemoryReleasedException;
import org.voovan.tools.log.Logger;

import java.nio.ByteBuffer;


/**
 * Socket消息处理类
 *
 * @author helyho
 *
 * Voovan Framework.
 * WebSite: https://github.com/helyho/Voovan
 * Licence: Apache v2 License
 */
public class MessageLoader {

	private IoSession session;
	private StopType stopType;
	private ByteBufferChannel byteBufferChannel;

	/**
	 * 构造函数
	 * @param session Session 对象
	 */
	public MessageLoader(IoSession session) {
		this.session = session;
		//准备缓冲流
		byteBufferChannel = session.getReadByteBufferChannel();
	}


	public enum StopType {
		RUNNING,
		SOCKET_CLOSED,
		STREAM_END,
		MSG_SPLITTER,
		EXCEPTION
	}

	/**
	 * 获取停止类型
	 * @return 停止类型
	 */
	public StopType getStopType() {
		return stopType;
	}

	/**
	 * 设置停止类型
	 * @param stopType 停止类型
	 */
	public void setStopType(StopType stopType) {
		this.stopType = stopType;
	}

	/**
	 * 判断字节所属流是否结束
	 * @param length  长度
	 * @return 是否意外断开
	 */
	public static boolean isStreamEnd(int length) {
//		length==-1时流结束
		if(length==-1){
			return true;
		}

		return false;
	}

	/**
	 * 判断字节所属流是否结束
	 * @param buffer  缓冲区
	 * @param length  长度
	 * @return 是否意外断开
	 */
	public static boolean isStreamEnd(byte[] buffer, int length) {

		if(length==-1){
			return true;
		}

		return false;
	}

	/**
	 * 关闭 MessageLoader
	 */
	public void close(){
		stopType = StopType.SOCKET_CLOSED;
	}


	/**
	 * 读取 socket 中的数据
	 * 	逐字节读取数据,并用消息截断器判断消息包是否完整,消息粘包有两种截断方式:
	 * 	1.消息截断器生效
	 * 	2.消息读取时间超时,例如设置5m,则连续5秒内没有读取到有用的消息则返回报文.
	 * @return 读取的缓冲区数据
	 */
	public int read() {
		int splitLength = 0;

		int oldByteChannelSize = 0;

		ByteBuffer dataByteBuffer = null;

		stopType = StopType.RUNNING;

		if(session==null){
			return -1;
		}

		//获取消息分割器
		MessageSplitter messageSplitter = session.socketContext().messageSplitter();

		if(messageSplitter==null){
			Logger.error("[Error] MessageSplitter is null, you need to invoke SocketContext object's messageSplitter method to set MessageSplitter Object in it.");
			return -1;
		}

		boolean isConnect = true;

		while (isConnect && stopType == StopType.RUNNING && !byteBufferChannel.isEmpty()) {

			if(session.socketContext().getConnectType() == ConnectType.UDP) {
				isConnect = session.isOpen();
			}else {
				isConnect = session.isConnected();
			}

			//如果连接关闭,
			if(!isConnect){
				stopType = StopType.SOCKET_CLOSED;
				return -1;
			}

			int readsize = byteBufferChannel.size() - oldByteChannelSize;

			try {
				dataByteBuffer = byteBufferChannel.getByteBuffer();
				try {

					//判断连接是否关闭
					if (isStreamEnd(byteBufferChannel.size())) {
						stopType = StopType.STREAM_END;
					}

					//使用消息划分器进行消息划分
					if (readsize==0 && dataByteBuffer.hasRemaining()) {
						if (messageSplitter instanceof TransferSplitter) {
							splitLength = dataByteBuffer.limit();
						} else {
							//拦截心跳
							while(HeartBeat.interceptHeartBeat(session)){

							}
							splitLength = messageSplitter.canSplite(session, dataByteBuffer);
						}

						if (splitLength >= 0) {
							stopType = StopType.MSG_SPLITTER;
							break;
						} else {
							//消息不可分割,且有消息报文存在, 则尝试继续从 Socket 通道读取数据
							session.getSocketSelector().select();
						}
					}
				} finally {
					byteBufferChannel.compact();
				}

				oldByteChannelSize = byteBufferChannel.size();
			}catch(MemoryReleasedException e){
				stopType = StopType.SOCKET_CLOSED;
			}
		}

		//如果是流结束,对方关闭,本地关闭这三种情况则返回 null
		// 返回是 null 则在EventProcess中直接返回,不做任何处理
		if (stopType == StopType.STREAM_END ||
				stopType == StopType.SOCKET_CLOSED) {
			return -1;
		}

		//如果是消息截断器截断的消息则调用消息截断器处理的逻辑
		else if (stopType == StopType.MSG_SPLITTER) {
			if (splitLength >= 0) {
				return splitLength;
			} else {
				return -1;
			}
		} else {
			return -1;
		}


	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy