나만의 Decoder를 만들어 보자
VS Code 프로젝트 생성
VS Code에서 cmd+shift+p 누르고 Java Project 생성
입력창에 java라고 입력하면 Create Java Project 선택
나중에 gradle이나 maven을 해야겠지만 셋팅 귀찮음.
걍 빌드툴없이 프로젝트 생성하자. ( 필요한 파일들은 한땀한땀 옮겨야 한다.)
저장할 폴더를 선택하고 프로젝트명을 생성한 뒤 필요한 파일을 옮기자
JUnit, Log4J2 with Slf4j(설정파일포함-간단한거 가져옴), Netty를 가져오자
어떤걸 만들어볼까?
예제샘플에 많이 나오는 숫자를 보내면 절대값으로 바꿔주는걸 만들어보자.
첫번째. LoggingHandler를 달고,
두번째. Decoder내에서 ByteBuf를 받아서 Integer로 리턴한다.
세번째. ChannelHandler에서 받아서 다시 리턴한다.
네번째. Encoder에서 ByteBuf로 바꿔서 보낸다.
첫번째. Logger 정의하고, EmbeddedChannel 정의하고 , CCTV달고.
ublic class DecoderExample {
private final Logger logger = LoggerFactory.getLogger(ChannelTest.class); // logger달고
@Test // JUnit Annotation이다..
public void DecoderTest() {
EmbeddedChannel channel = new EmbeddedChannel(); // 카페 오픈
channel.pipeline().addLast(new LoggingHandler(LogLevel.INFO)); //cctv달자
}
}
두번째. Decoder를 달자.
별도로 java파일을 만들어야 하는데 구찮아서 동일 파일에 넣어버렸다.
ByteToMessaggeDecoder를 상속받아서 만들면 반드시 decode 함수를 정의하고 input은 ByteBuf 이고, out 파라미터가 붙는다
out에다 담으면 "다음 놈 받아" 가 된다.
class MyDecoder extends ByteToMessageDecoder {
private final Logger logger = LoggerFactory.getLogger(App.class); // logger달고
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
logger.info("decode start.. {}", in.getInt(0)); //한번 읽어보자
out.add(Math.abs(in.readInt())); // 읽어서 out에 담아서 PASS!!
logger.info("decode end.. ");
}
}
세번째. channelHandler를 만들어서 리턴하자
여기도 별거 없다. Decoder에서 받은걸 찍고 다시 보낸다.. 마치 Echo 서버 처럼
class MyChannelHandler extends ChannelInboundHandlerAdapter {
private final Logger logger = LoggerFactory.getLogger(App.class); // logger달고
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
logger.info("Read .. {}", (Integer) msg);
ctx.channel().writeAndFlush(msg); // 다시 쏜다
}
}
다음에 EmbeddedChannel에 writeInbound를 날려보자
import java.util.List;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
public class DecoderExample {
private final Logger logger = LoggerFactory.getLogger(ChannelTest.class); // logger달고
@Test
public void DecoderTest() {
EmbeddedChannel channel = new EmbeddedChannel();
channel.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
channel.pipeline().addLast(new MyDecoder());
channel.pipeline().addLast(new MyChannelHandler());
//channel.pipeline().addLast(new MyEncoder());
ByteBuf inBuf = Unpooled.buffer(4); // 4byte Integer
inBuf.writeInt(-10);
channel.writeInbound(inBuf);
ByteBuf readBuf = (ByteBuf)channel.readOutbound(); //읽어드려보자
logger.info("readBuf = {}", readBuf.readInt());
channel.finish(); // 쓰기종료
}
}
class MyDecoder extends ByteToMessageDecoder {
private final Logger logger = LoggerFactory.getLogger(App.class); // logger달고
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
logger.info("decode start.. {}", in.getInt(0));
out.add(Math.abs(in.readInt()));
logger.info("decode end.. ");
}
}
class MyChannelHandler extends ChannelInboundHandlerAdapter {
private final Logger logger = LoggerFactory.getLogger(App.class); // logger달고
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
logger.info("Read .. {}", (Integer) msg);
ctx.channel().writeAndFlush(msg);
}
}
오류가 발생했다
java.lang.ClassCastException: class java.lang.Integer cannot be cast to class io.netty.buffer.ByteBuf
MyChannelHandler에는 MyDecoder에서 전달받은 Integer가 담겨있고 그걸 다시 보냈으니 받을때 오류가 난것이다.
ByteBuf readBuf = channel.readOutbound() 로 바꿔서
돌려보자.
그럼 정상적으로 10이 찍힌다.
'프로그래밍 > Netty Encoder & Decoder' 카테고리의 다른 글
Netty Encoder with VSCode (1) (0) | 2022.01.10 |
---|---|
Netty Encoder & Decoder (0) | 2022.01.10 |
Netty Encoder with VSCode (0) | 2022.01.06 |
Netty Decoder with VS Code (1) (0) | 2022.01.06 |