나는 다음과 같은 형식으로 메시지를 처리하기 위해 내 handlers
및 codecs
테스트 할 EmbeddedChannel
을 사용하고 있습니다 : 나는 무엇을 달성하고자, 첫째의 Netty ByteToMessageCodec <ByteBuf> 디코딩 메시지를 두 번 (부분적으로)
+------------+------------------+----------------+
| Header | Payload Length | Payload |
| 16 bytes | 2 bytes | "Some data" |
+------------+------------------+----------------+
:
- 헤더 세부 정보를 저장할 개체를 생성하여 처음 16 바이트를 처리하고 나중에 사용하기 위해
ChannelHandlerContext
의AttributeMap
에 디코딩 된 헤더 개체를 추가합니다. - 전체 페이로드 데이터를 기다리거나 검색합니다.
- 헤더 객체와 전체 페이로드가 최종 처리기에서 메시지를 라우팅 할 수 있도록
ByteBuf
으로 사용할 수 있습니다.
나는 다음과 같은 처리기를 사용하여 :
ByteToMessageCodec<ByteBuf>
헤더 정보를 추출하고 속성 목록에 추가 할 수 있습니다.LengthFieldBasedFrameDecoder
페이로드 길이를 읽고 전체 프레임을 기다리거나 검색 할 수 있습니다.SimpleChannelInboundHandler
이 속성 목록에서 검색된 헤더 객체를 사용하여 그에 따라 페이로드를 라우팅합니다.
메시지가 ByteToMessageCodec
의 decode
메서드로 전달되면 헤더가 올바르게 처리되고 추출됩니다. 그런 다음 AttributeMap
에 Header 개체를 계속 추가하고 ByteBuf
(이는 readableBytes = 2 바이트 (페이로드 길이 표시기 + 페이로드 길이)가 있음)을 추가합니다.
페이로드 길이가 1020 바이트라고 가정 해 봅니다. 메시지는 처음에 codec
에 의해 수신되고 readableBytes = 16 bytes + 2 bytes + 1020 bytes
이됩니다. 헤더는 decode
메서드에 의해 읽혀지고 나머지 바이트 (1022)는 List<Object> out
에 추가됩니다.
내 이해가 정확하면
는, 바이트의 나머지는 이제 길이 표시기를 읽고SimpleChannelHanlder
에 페이로드 (1020 바이트)를 전달합니다
LengthFieldBasedFrameDecoder
입니다 다음 핸들러에 전달 될 것입니다,하지만 난 착각한다.
decode
메서드는 에 추가 된 것과 동일한 1022 바이트를 사용하여으로 다시 이라고합니다. 이 디코드 방법의 JavaDoc을에서
Decode the from one ByteBuf to an other. This method will be called till either the input ByteBuf
has nothing to read when return from this method or till nothing was read from the input ByteBuf.
이 decode
이 readableBytes == 0
때까지 호출됩니다 의미합니까? 나머지 메시지를 LengthFieldBasedFrameDecoder
으로 전달하는 가장 효율적인 방법은 무엇입니까?
readerIndex = 0
을 설정하고 List<Object> out
에 ByteBuf의 사본을 추가해야이 평균이 수행의 LengthFieldBasedFrameDecoder
이 입력으로 ByteBuf
필요 같은데요? 어떤 도움/조언/비판도 받아 들여질 것입니다. 가능한 한 가장 깨끗한 방법으로이 작업을 수행하고 싶습니다.
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
byte [] headerBytes = new byte[HEADER_LENGTH];
in.readBytes(headerBytes, 0, HEADER_LENGTH);
Header header = new Header(headerBytes);
System.out.println("Decoded Header: \n" + header);
//Set the header attribute so it can be used by routing handlers
ctx.attr(ChannelAttributes.HEADER).getAndSet(header);
//pass to next handler
out.add(in);
}
참고 : 여기에
내 decode
방법이다 나는 Netty in Action MEAP v8
감사합니다. 'setSingleDecode (true)'가 필요한 것입니다. 그러나 'ByteToMessageCodec'을 구현할 때 메서드를 찾지 못하고 ByteToMessageDecoder 만 나타납니다. 상관없이 인코딩 및 디코딩 프로세스가 분리됩니다. 그리고 '헤더'를 다음 핸들러에 전달하는 팁을 주셔서 감사합니다. 나는'ctx.channel(). attr (ChannelAttributes.HEADER) .set (header)'를 실행하여 채널의'AttributeMap'에 그것을 추가함으로써'header'를 설정하고 가져올 수있었습니다. 이 모든 단점은? – Ian2thedv
아, 네,'setSingleDecode'는'ByteToMessageDecoder'에만 존재합니다. 채널의 속성 맵에 대해서는 단점이없는 것으로 나타났습니다. 이는 확실히 실용적인 솔루션입니다. – knutwalker