#java #sockets #tcp #netty
Вопрос:
Я нахожусь в процессе изучения Netty и пытаюсь создать клиентско-серверную программу для передачи пользовательских пакетов с помощью ByteBuf
. Моя главная проблема, однако, заключается в том, что один из моих #channelActive
методов не вызывается, и я не понимаю, почему.
Чтобы дать немного контекста, у меня есть PacketHandlerBoss
и InitialHandler
, оба из которых обрабатывают входящие PacketWrapper
объекты.
public class PacketHandlerBoss extends ChannelInboundHandlerAdapter {
private ChannelWrapper channelWrapper;
@Setter
private PacketHandler packetHandler;
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("! ! ! Called channelActive in PacketHandlerBoss ! ! !");
if (this.packetHandler != null) {
this.channelWrapper = new ChannelWrapper(ctx);
this.packetHandler.connected(this.channelWrapper);
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (this.packetHandler != null) {
this.channelWrapper.markClosed();
this.packetHandler.disconnected(this.channelWrapper);
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (this.packetHandler != null) {
PacketWrapper wrapper = (PacketWrapper) msg;
boolean shouldHandle = this.packetHandler.shouldHandle(wrapper);
try {
if (shouldHandle amp;amp; wrapper.getPacket() != null) {
wrapper.getPacket().handle(this.packetHandler);
}
if (shouldHandle) {
this.packetHandler.handle(wrapper);
}
} finally {
wrapper.singleRelease();
}
}
}
}
public class InitialHandler extends PacketHandler {
private ChannelWrapper channelWrapper;
@Override
public boolean shouldHandle(PacketWrapper packet) {
return !this.channelWrapper.isClosing();
}
@Override
public void connected(ChannelWrapper channelWrapper) {
this.channelWrapper = channelWrapper;
}
@Override
public void disconnected(ChannelWrapper channelWrapper) {}
@Override
public void exception(Throwable t) {}
@Override
public void handle(PacketWrapper packetWrapper) {
if (packetWrapper.getPacket() == null) {
throw new QuietException("Unexpected packet received! " ByteBufUtil.hexDump(packetWrapper.getBuf(), 0, Math.min(packetWrapper.getBuf().writerIndex(), 16)));
}
}
}
Ошибка возникает из this.packetHandler.shouldHandle(wrapper)
-за . Трассировка стека говорит , что this.channelWrapper
это значение равно нулю InitialHandler
, но я устанавливаю экземпляр InitialHandler#connected
, который вызывается PacketHandlerBoss#channelActive
.
Я запустил программу с инструкцией печати в channel active, и ничего не печатается, то есть активный канал не вызывается PacketHandlerBoss
. Я не понимаю, почему это так…
Ниже PipelineUtils
приведен класс, который управляет всеми обработчиками:
public class PipelineUtils {
public static final Base BASE = new Base();
public static final String TIMEOUT_HANDLER = "timeout";
public static final String BOSS_HANDLER = "boss_handler";
public static final String PACKET_ENCODER = "packet_encoder";
public static final String PACKET_DECODER = "packet_decoder";
public static final String CHANNEL_REGISTRAR = "channel_registrar";
public static final ChannelInitializer<Channel> PROXY_CHILD_HANDLERS = new ChannelInitializer<>() {
@Override
protected void initChannel(Channel channel) {
try {
PipelineUtils.BASE.initChannel(channel);
} catch (Exception e) {
e.printStackTrace();
channel.close();
return;
}
channel.pipeline()
.addBefore(PipelineUtils.TIMEOUT_HANDLER, PipelineUtils.PACKET_DECODER, new MinecraftDecoder(Protocol.GAME, true))
.addBefore(PipelineUtils.BOSS_HANDLER, PipelineUtils.PACKET_ENCODER, new MinecraftEncoder(Protocol.GAME, true))
.get(PacketHandlerBoss.class).setPacketHandler(new InitialHandler());
}
};
private static final class Base extends ChannelInitializer<Channel> {
@Override
protected void initChannel(Channel channel) {
channel.pipeline()
.addLast(PipelineUtils.TIMEOUT_HANDLER, new ReadTimeoutHandler(30000, TimeUnit.MILLISECONDS))
.addLast(PipelineUtils.BOSS_HANDLER, new PacketHandlerBoss());
}
}
}
Комментарии:
1. Не могли бы вы также добавить код, который показывает, как вы используете
ServerBootstrap
etc ?