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

org.fastquery.tcpserver.MessageDecoder Maven / Gradle / Ivy

The newest version!
package org.fastquery.tcpserver;

import static org.fastquery.tcpserver.Server.FIXEDTLEN;
import static org.fastquery.tcpserver.Server.START;

import java.net.InetSocketAddress;
import java.util.List;
import org.fastquery.bytes.CRC16;
import org.fastquery.bytes.ShortByteUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

// 解包
public class MessageDecoder extends ByteToMessageDecoder {
	
	private static final Logger LOG = LoggerFactory.getLogger(MessageDecoder.class);
	
	private Conf conf;
	
	public MessageDecoder(Conf conf) {
		this.conf = conf;
	}
	
	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception {
		// buf 中可读字节
		int canReadLen = in.readableBytes();
		LOG.info("decodeing,readableBytes: {}",canReadLen);
		if(canReadLen > conf.getMaxPkg()) {
			in.skipBytes(canReadLen);
			LOG.error("传递的包太大,{}b,已经将其丢弃,channel:{}",canReadLen,ctx.channel());
			return;
		}
		InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress(); 
		String remoteAddress = insocket.getAddress().getHostName();
		
		int uriLen = 0;
		int idLength = 0;
		int msgLength = 0;
		int attachmentType = 0;
		int attachmentLength = 0;

		int currentLen = -1; // 当前包的长度, -1 表示还没有找到包头
		int thisPkgLen = 0; // 这个包应该的长度
		byte[] onePkg = new byte[FIXEDTLEN]; // 初始化 一个包的大小
		byte lastByte = 0X00; // 记录上一个字节
		
		while(in.readableBytes() > 0) {

				byte current = in.readByte();

				if (START == current) {
					if (lastByte == START) {
						lastByte = 0;
					} else {
						lastByte = START;
						continue;
					}
				} else {
					if (lastByte == START) {
						currentLen = 0;
						onePkg[currentLen++] = START;
					}
					lastByte = current;
				}

				if (currentLen != -1) { // 如果当前状态已经找到包头
					onePkg[currentLen++] = current;
				}
				
				if (currentLen == FIXEDTLEN) {
					uriLen = onePkg[6] & 0XFF;
					idLength = onePkg[7] & 0XFF;
					msgLength = ShortByteUtil.toUnsignedInt(onePkg[8], onePkg[9]);
					attachmentType = onePkg[10] & 0XFF;
					attachmentLength = ShortByteUtil.toUnsignedInt(onePkg[11], onePkg[12]);
					thisPkgLen = FIXEDTLEN + uriLen + idLength + msgLength + attachmentLength + 2;
					// 对onePkg 进行扩容
					byte[] tmpbs = new byte[thisPkgLen];
					// 将当前 onePkg copy 至 tmpbs 里
					System.arraycopy(onePkg, 0, tmpbs, 0, currentLen);
					onePkg = tmpbs;
				} else if (currentLen == thisPkgLen) {
					
						// CRC 校验
						byte[] crc = CRC16.updateCRC(onePkg, thisPkgLen - 2);
						if (crc[0] == onePkg[thisPkgLen - 2] && crc[1] == onePkg[thisPkgLen - 1]) {
							Transmission t = Convert.toTransmission(onePkg, uriLen, idLength, msgLength, attachmentType, attachmentLength);
							out.add(t);
							in.markReaderIndex();
							LOG.info("已读到一个完整包: {}",t);
						} else {
							LOG.error("客户端IP:{}, 校验失败了,msg长度: {}, attachmentLength:{}, idLength={}", remoteAddress,msgLength, attachmentLength, idLength);
						}
						
						return;
				}
		}
		
		in.resetReaderIndex();
	}
}