关闭

MINA通信deCode实现

标签: session通信数据
571人阅读 评论(0) 收藏 举报
分类:
public class SocketServerDecoder extends CumulativeProtocolDecoder {
private static final Logger log = Logger.getLogger(SocketServerDecoder.class);
public static final boolean ifPrintDebugInfo=false;
private Charset charset =null;
private static final String ATTRIBUTE_NAME="HelperMsgInfo";

public SocketServerDecoder(Charset charset) {
this.charset=charset;
log.debug("Server端#SocketServerDecoder构造方法,当前线程:"+Thread.currentThread().getId());
}

@Override
protected boolean doDecode(IoSession session, IoBuffer ioBuffer,
ProtocolDecoderOutput out) throws Exception {
ioBuffer.order(ByteOrder.LITTLE_ENDIAN);
log.debug("Server端#doDecode#剩余客户端消息大小:"+ioBuffer.remaining());
sysPrintLn("Server端#doDecode#ioBuffer读到剩余客户端消息大小:"+ioBuffer.remaining());
MessageInfo hmi=null;
String attrStr=ATTRIBUTE_NAME+session.getId();
Object o=session.getAttribute(attrStr);
if(null!=o && (o instanceof MessageInfo)){
hmi=(MessageInfo)o;
}
//修改缓冲区的字节顺序为little-endian,按照此顺序,多字节值的字节顺序是从最低有效位到最高有效位的。
    if(null==hmi){
    sysPrintLn("null==hmi");
    if(ioBuffer.remaining()>4){
    sysPrintLn("ioBuffer.remaining()>4");
    hmi=new MessageInfo();
    short  bodyLength= ioBuffer.getShort();
    short  msgIdentify=ioBuffer.getShort();
    hmi.setMsgBodySize(bodyLength);
    hmi.setMsgIdentify(msgIdentify);
    sysPrintLn("ioBuffer.position [null==hmi]:"+ioBuffer.position());
    sysPrintLn("bodyLength:"+bodyLength);
    sysPrintLn("msgIdentify:"+msgIdentify);
    session.setAttribute(attrStr,hmi);
    sysPrintLn(" [null==hmi]将再次调用当前解码方法!");
    return true;
    }else{
    sysPrintLn("ioBuffer.remaining()<=4");
    sysPrintLn("将继续接收!");
    return false;
    }
    }else{
    sysPrintLn(" [null!=hmi]");
    sysPrintLn("剩余byte大小1:"+ioBuffer.remaining());
if (ioBuffer.remaining() >= hmi.getMsgBodySize()) {
sysPrintLn("ioBuffer.remaining() >= hmi.getMsgbodySize()!");
/*
* 检查缓冲区的可用字节数是否大于等于消息体长度,即是否读取到消息体了。
*/
byte[] messageBody = new byte[hmi.getMsgBodySize()]; // 创建定长的数组存放消息体
ioBuffer.get(messageBody); // 从缓冲区中读取bodyLength字节的数据填充进数组
String msgbody = new String(messageBody,charset); // 设置请求的消息体
sysPrintLn("msgbody:"+msgbody);
hmi.setMsgBody(msgbody);
/*
* 将session对象的“HelperMsgInfo”键及其对应的属性值移除从而:
* 1、将bodySize键设置成无值状态,代表消息体已经解析完成。再次进入等待解析消息头阶段
* 2、释放存储“HelperMsgInfo”键的属性值占用的内存。
*/
session.removeAttribute(attrStr);
/*
* 将解码后生成的请求对象对象抛给位于应用层的Handler处理,或者抛给下一层解码器(如果存在)。
*/
out.write(hmi);
/*
* 因为当一条完整消息解析完成后,这时缓冲区内可能还有足够的积累数据可以继续解析下一条消息(也可能没有),
* 返回true使框架再次调用doDecode方法 。 
* 即使缓冲区内没有足够的数据了,也应该留给下次调用doDecode方法时去判断。
*/
sysPrintLn("[null!=hmi]将再次调用当前解码方法!");
return true;
} else {
sysPrintLn("ioBuffer.position *****:"+ioBuffer.position());
sysPrintLn("剩余byte大小 ****:"+ioBuffer.remaining());
sysPrintLn("ioBuffer.remaining() < hmi.getMsgbodySize()!");
/*
* 如果缓冲区内可用字节个数不足以构成完整的消息体,
* 直接返回false告诉框架不要再回调doDecode方法,
* 直到网络获取到数据压进缓冲区时再调用
*/
sysPrintLn("将继续接收!");
return false;
}
    }
}

private void sysPrintLn(String s){
if(SocketServerDecoder.ifPrintDebugInfo){
System.out.println(s);
}
}
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:2508次
    • 积分:77
    • 等级:
    • 排名:千里之外
    • 原创:5篇
    • 转载:0篇
    • 译文:0篇
    • 评论:3条
    文章分类
    文章存档
    最新评论