2013년 6월 11일 화요일

mina - CumulativeProtocolDecoder

0. MINA를 이용해 TCP/IP 통신을 구현하는 중 MINA IoBuffer에 하나의 msg가 쪼개지거나, 2~3개의 msg가 동시에 들어오는 현상이 있어서 구글링을 좀 했다.

1. CumulativeProtocolDecoder?
 - ProtocolDecoder that cumulates the content of received buffers to a cumulative buffer to help users implement decoders.
If the received IoBuffer is only a part of a message. decoders should cumulate received buffers to make a message complete or to postpone decoding until more buffers arrive.
 - 일단 api에 설명이 잘 나와 있다. (MINA는 문서화가 잘 안 되어 있어서 머리가 아플때가 좀 있는데 예제까지 있다.)

2. decode()
 - CumulativeProtocolDecoder 클래스의 핵심은 decode() method로 msg 처리가 끝나면 true를 리턴하면 되고, IoBuffer가 다 채워지지 않은 상태면 false를 리턴하면 된다. 
 - false를 리턴 한 후 다시 decode()가 호출 될 때 IoBuffer를 살펴 보면 이전에 받은 msg와 새로 받은 msg가 함께 들어 있다.
 - 따라서 온전한 packet인지 여부를 판단하여 모든 byte가 다 들어 올 때까지 기다리는 로직등이 구현되어야 한다.

3. tip
 - IoBuffer라는 것은 MINA에서 사용하는 byte buffer 다.
 - 혹은 ByteBuffer를 참고하면 되겠다.

 - http://docs.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html

4. sample code (extends CumulativeProtocolDecoder)
    @Override
    protected boolean doDecode(IoSession session, IoBuffer in,
            ProtocolDecoderOutput out) throws Exception {
        int start = in.position();
        int limit = in.limit();
        int winLen, pktLen = 0;
        byte[] b;
        in.position(start);
        while (in.hasRemaining()) {
            winLen = limit - start;
            // STX check
            if(in.get(start) != 0x02){
                in.skip(in.remaining());
                return true;
            }
            // header check
            if(winLen > HEADER_LENGTH){
                pktLen = getFullLength(in, start);
                // length check
                if(pktLen > winLen)
                    return false;
                // ETX check
                if(in.get(start + pktLen -1) != 0x03){
                    in.skip(in.remaining());
                    return true;
                }
            }else{
                return false;
            }
            // write
            b = new byte[pktLen];
            in.get(b);
            out.write(b);
            start = in.position();
        }
        return true;
    }

댓글 없음:

댓글 쓰기