본문 바로가기
프로그래밍/Netty Codec 이해하기

Netty Pipeline 및 Codec 활용(2)

by Flow.X 2022. 1. 7.
728x90

앞에서 말했던 pipeline을 좀더 조작해보자 

 

여기서 해볼꺼는 ByteBuf 로 받는거를 String으로 변환하는 Codec을 추가해서 귀찮은 형변환을 간단하게 해보고

엔터키가 오면 그걸 잘라서 처리해보고자 한다.

 

데이터를 받을때 ByteBuf로 기본으로 받다보니 변환해서 사용해야했다

 

 

우선 CodeSampleHandler.java의 channelRead 코드를 보면

Object msg -> ByteBuf -> String으로 변환한 뒤 사용했다. 

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        String strRecv = ((ByteBuf) msg).toString(CharsetUtil.UTF_8);
        logger.info("channelRead.. READ : {}", strRecv);

        String strReturn = ">> " + strRecv;
        ByteBuf buf = PooledByteBufAllocator.DEFAULT.buffer(strReturn.length()); // 필요한 길이만큼 할당
        buf.writeBytes(strReturn.getBytes(CharsetUtil.UTF_8)); // 얻어온 ByteBuf에 쓰기
        ctx.channel().writeAndFlush(buf); // 보내기
    }

디버깅을 해보면 msg 이놈이 ByteBuf로 온다.

String으로 받으면 좀 편할텐데.. 

vscode debug 모드

Codec을 추가해보자. 

 

LoggingHandler (ByteBuf) ▶ StringDecoder (string) ▶ CodeSamplerHandler (String) ▶ StringEncoder (ByteBuf)

로 쭉 흘러간다. 괄호 안은 어떻게 데이터가 형변환 되어 있는지 보여준다 

 

CodecSample.java 수정

b.childHandler(new ChannelInitializer<SocketChannel>() {
    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        // 손님 들어왔을때 대응메뉴얼
        logger.info("손님 문열고 들어옵니다..");
        ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));

        ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
        ch.pipeline().addLast(new CodecSampleHandler());

        ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
    }
});

CodeSampleHandler.java 수정

msg를 String으로 변환해서 이제 바로 쓸수 있다 

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        String strRecv = (String) msg; // String으로 변환
        logger.info("channelRead.. READ : {}", strRecv);

        String strReturn = ">> " + strRecv;
        ctx.channel().writeAndFlush(strReturn); // 보내기
    }

디버깅 해서 보면 String으로 표시된다.

StringDecoder추가 후 모습

Hi 뒤에 보면 뭔가 또 달려있는게 보인다.  저걸 없애보자. 

 

손님이 와서 주문을 하는데 주문이 끝날때는 카드를 내밀어야 한다. 주문이 끝나기도 전에 카드를 내밀면 무조건 결제하고, 추가주문을

받는다는 원칙을 세웠다고 하자. 

 

그럼 고객은 항상 주문이 완료되면 카드를 내밀것이다. 그걸 캐치해서 다음 단계로 진행시키고, 이후 다시 주문받고 하면 되겠다.

ChannelHandler 중 Netty 샘플에서 가장많이 쓰는것이 아래 두개이다

 

LineBasedFrameDecoder : 라인단위로 가져와서 처리
LengthFieldBasedFrameDecoder :  앞에다가 내가 보낼 사이즈는 얼마야 라고 먼저 보내고 이야기를 하는것 

그 중 LineBasedFrameDecoder 를 써보자

우선 설명을 보면 받은 ByteBuf를  \n, \r\n으로 나눈다고 한다 

LineBasedFrameDecoder 설명

함수에 커서를 두고 cmd + . (맥기준) 을 누르면 아래와 같이 설명이 나온다.

여기서 설명을 보면 최대길이를 지정하라고 되어 있네.. 

LineBasedFrameDecoder 함수파라미터

CodeSample에 추가한 모습이다.

이제는 이렇게 흘러간다

LoggingHandler ▶ LineBasedFrameDecoder ▶ StringDecoder ▶ CodeSamplerHandler ▶ StringEncoder

b.childHandler(new ChannelInitializer<SocketChannel>() {
    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        // 손님 들어왔을때 대응메뉴얼
        logger.info("손님 문열고 들어옵니다..");
        ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
        ch.pipeline().addLast(new LineBasedFrameDecoder(10));
        ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
        ch.pipeline().addLast(new CodecSampleHandler());

        ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
    }
});

실행해보자. 깔끔하게 짤렷다.

추가 안했을때 모습을 다시보자. 뒤에 뭔가가 붙어있다. 

LineBasedFramdeDecoder 삭제 시

 

앞에서 maxlength를 10으로 했는데 만약 오버하면 어떻게 될까?

아래처럼 오류가 나고, 다음 코드는 아에 수행이 안된다.

기본적으로 손님이 왔을때 진상이면 거부도 할수 있겠구나 싶다.

LineBasedFrameDecoder maxlength 오류

728x90