Netty에는 다양한 Codec이 있다.
그걸 사용하면 왠만한 모든것들을 다 처리할수가 있을정도로 잘 되어 있다.
그중 Decoder에 대해 살펴보자
Decoder들은 아래 3개를 상속받아서 구현되어 있고, 자기만의 Decoder, Encoder를 만들수도 있다.
ByteToMessageDecoder
여기에서 기본적으로 지원하는 디코더를 볼수 있다.
ByteBuf를 내가 원하는 메시지 형태로 변경할 수 있다.
대부분 처음 수신될때 ByteBuf로 수신되기 때문에 pipeline 제일 앞쪽에 배치가 된다.
카페를 예를들면
우리나라 말로 한다고 한들 팔도 사투리가 다 들어올 것이다.
그럼 팔도 사투리들을 ByteBuf로 생각하고 종업원은 경상도 사람인데 (channelHandler로 보고) 미리 경상도로 바꿔 줬으면 좋겠다라고 하면 이렇게 배치될것 같다.
channel.pipeline.addLast(new 팔도사투리를경상도사투리로());
channel.pipeline.addLast(new 경상도종업원이처리()); // 주문처리
팔도사투리를_경상도사투리로() 코드를 보면
ByteBuf형태의 msg를 받아서 경상도 사투리로 리턴되서 나온다
여기서 중요한점은 decode는 반드시 있어야 하는 함수이다.
public class 팔도사투리를_경상도사투리로() extends ByteToMessageDecoder<ByteBuf>{
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
out.add(경상도사투리로(msg)); //경상도 사투리로 변환
}
}
MessageToMessageDecoder
Bytebuf가 아닌 메시지를 다른 메시지로 변환할 수 있다.
여기에서 기본적으로 제공되는 디코더를 볼수 있다
다시 카페를 예로 들면, 종업원이 경상도인데 마산 사람이야.. 근데 손님은 경상도 사람인디 대구사람이네..
pipeline은 이렇게 구성되고
channel.pipeline.addLast(new 팔도사투리를_경상도사투리로()); // bytebuf -> 경상도사투리 (message)
channel.pipeline.addLast(new 대구사투리를_마산사투리로()); // 대구사투리면(message) -> 마산으로 (message)
channel.pipeline.addLast(new 마산종업원이처리()); // 주문처리
대구사투리를_마산사투리로는 이렇게 처리되겠지
public class 대구사투리를_경상도사투리로() extends ByteToMessageDecoder<경상도사투리>{
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
if(msg instanceof 대구사투리){
out.add(대구사투리를_마산사투리로(msg)); //마산사투리로 변환
}
}
}
ReplayingDecoder
ByteToMessageDecoder를 상속받아서 만들어진 Decoder로 ByteToMessageDecoder를 좀더 편하게 사용하기 위해 만들어졌다.
카페에 손님이 왔는데 이 손님이 말을 더듬어서 어디 사투리인지 모를 때 내가 알아들을 만큼 말할때까지 기다릴때 사용하면 될것같다.
public class 기다리자말끝날때까지() extends ReplyingDecoder<ByteBuf>{
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
out.add(엔터키칠때까지읽자(msg));
}
}
그런데 ReplayingDecoder 는 성능상에 문제를 발생시킬수도 있기 때문에 checkpoint를 사용해야 한다고 한다.
알아들을때까지에 대한 부분을 기다리기 때문인듯하다.
ReplayingDecoder에 checkpoint()를 넣자
public class 기다리자말끝날때까지() extends ReplyingDecoder<ByteBuf>{
Enum 손님말 {"말할단어수","한말"}
int length =0;
public 기다리자말끝날때까지(){
checkpoint(손님말.말할단어수); // 고객 인사를 기다린다.
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
switch (state()) {
case 손님말.말할단어수:
length = buf.readInt(); // 고객이 말할 단어수를 읽을때까지 기다름
checkpoint(손님말.한말); // 다음꺼는 고객이 한말이 말할단어수만큼 오겠군
break.
case 손님말.한말:
ByteBuf frame = buf.readBytes(length); // 고객이 말할단어수만큼 읽는다
checkpoint(손님말.말할단어수); //다음은 말할 단어수니깐 그걸로 초기화
out.add(frame);
break;
default:
throw new Error("Shouldn't reach here.");
}
}
}
만약 ByteToMessageDecoder 를 사용하게 된다면 아래처럼 구현될것 이다.(적당한가.. 나중에 다시보자)
public class 팔도사투리를_경상도사투리로() extends ByteToMessageDecoder<ByteBuf>{
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
if not (msg instanceof 팔도사투리 ) { // 알아 들을때까지 대기
return;
}
out.add(msg);
}
}
'프로그래밍 > Netty Encoder & Decoder' 카테고리의 다른 글
Netty Encoder with VSCode (1) (0) | 2022.01.10 |
---|---|
Netty Encoder & Decoder (0) | 2022.01.10 |
Netty Decoder with VSCode (2) (0) | 2022.01.07 |
Netty Encoder with VSCode (0) | 2022.01.06 |