#netty
#netty
Вопрос:
Я использую LengthFieldBasedFrameDecoder
в качестве своего первого обработчика для входящего трафика, который отправляется от клиента.
Длина: 4 байта Полезная нагрузка: Привет — 5 байт
[0, 0, 0, 9, 72, 101, 108, 108, 111]
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("frameDecoder", new PacketFrameDecoder());
ch.pipeline().addLast(new GameServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(port).sync();
ByteToMessageDecoder
Я вижу fireChannelRead(ctx, out, size)
, что вызывается с пустым out и размером 0. Похоже, что исключение не генерируется. Я пробовал оба порядка следования в декодере.
public class PacketFrameDecoder extends LengthFieldBasedFrameDecoder {
//Constants
private static final int MAX_FRAME_LENGTH = Integer.MAX_VALUE;
private static final int LENGTH_FIELD_OFFSET = 0;
private static final int LENGTH_FIELD_LENGTH = 4;
private static final int LENGTH_FIELD_ADJUSTMENT = 0;
private static final int INITIAL_BYTES_TO_STRIP = 4;
//Constructors
public PacketFrameDecoder() {
super(MAX_FRAME_LENGTH, LENGTH_FIELD_OFFSET, LENGTH_FIELD_LENGTH,
LENGTH_FIELD_ADJUSTMENT, INITIAL_BYTES_TO_STRIP);
}
}
После этого я хочу обработать свое тело / полезную нагрузку в GameServerHandler
который расширяется ChannelInboundHandlerAdapter
.
public class GameServerHandler extends ChannelInboundHandlerAdapter {
/**
* This method is called with the received message, whenever new data is received from a client.
* @param context
* @param message
*/
@Override
public void channelRead(ChannelHandlerContext context, Object message) {
Log.i("GameServerHandler"); //Breakpoint here
ByteBuf in = (ByteBuf) message;
try {
String test = in.toString(io.netty.util.CharsetUtil.US_ASCII);
Log.i(test);
} finally {
ReferenceCountUtil.release(message);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
// Close the connection when an exception is raised.
cause.printStackTrace();
context.close();
}
}
Но channelRead
в моем GameServerHandler
не вызывается и не запускается. Я понятия не имею, что я делаю не так.
Ответ №1:
Я только что узнал, что проблема, похоже, связана с регулировкой длины. Мои заголовки (4 байта) включены в общую длину, поэтому есть 2 варианта:
- Вычтите длину заголовка из настройки поля длины:
LENGTH_FIELD_ADJUSTMENT = -4
- Не инкапсулируйте длину заголовка при отправке сообщения и содержите только полезную нагрузку