Нетти 4 чтение / запись в обработчике несколько раз

Я новичок в Netty, и я решил начать с 4.0.0, потому что я думал, что это должно быть лучше, потому что это новее. Мое серверное приложение должно получать данные от устройств gps, и процесс такой: сначала я получаю 2 байта, которые равны длине устройства imei, а затем я получаю imei с такой длиной, затем я должен отправить 0x01 устройство, если я хочу принять данные от него. После моего ответа устройство отправляет мне данные GPS с протоколом AVL. Теперь мой сервер работает без Netty, и я хочу изменить его на работу с Netty. Вот что я сделал:

Я создал серверный класс, как это

public class BusDataReceiverServer {

private final int port;
private final Logger LOG = LoggerFactory.getLogger(BusDataReceiverServer.class);

public BusDataReceiverServer(int port) {
    this.port = port;
}

public void run() throws Exception {
    LOG.info("running thread");
    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try{
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new BusDataReceiverInitializer());
        b.bind(port).sync().channel().closeFuture().sync();
    }catch (Exception ex){
        LOG.info(ex.getMessage());
    }
    finally {
        LOG.info("thread closed");
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

public static void main(String[] args) throws Exception {
    new BusDataReceiverServer(3129).run();
}

}

и создал класс инициализатора

public class BusDataReceiverInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();

        pipeline.addLast("imeiDecoder", new ImeiDecoder());
        pipeline.addLast("busDataDecoder", new BusDataDecoder());
        pipeline.addLast("encoder", new ResponceEncoder());

        pipeline.addLast("imeiHandler", new ImeiReceiverServerHandler());
        pipeline.addLast("busDataHandler", new BusDataReceiverServerHandler());
    }
}

Затем я создал декодеры и кодировщик и 2 обработчика. Мой imeiDecoder и кодировщик, и ImeiReceiverServerHandler работают. Это мой ImeiReceiverServerHandler

public class ImeiReceiverServerHandler extends ChannelInboundHandlerAdapter {

    private final Logger LOG = LoggerFactory.getLogger(ImeiReceiverServerHandler.class);

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageList<Object> msgs) throws Exception {
        MessageList<String> imeis = msgs.cast();
        String imei = imeis.get(0);

        ctx.write(Constants.BUS_DATA_ACCEPT);
        ctx.fireMessageReceived(msgs);

    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);    //To change body of overridden methods use File | Settings | File Templates.
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);    //To change body of overridden methods use File | Settings | File Templates.
    }
}

Теперь, после принятия я не понимаю, как продолжить получать данные GPS и переслать их в обработчик BusDataReceiverServerHandler. Если кто-то может помочь мне с этим или может предложить мне полезную документацию, я буду очень благодарен. Или, если это возможно сделать с Netty 3, за это я тоже буду благодарен.

1 ответ

Решение

Я не использовал Netty 4, поэтому я не уверен, что мой ответ будет точным на 100% или лучший способ сделать что-то в Netty 4, но вам нужно отслеживать состояние сеанса подключения / клиента, чтобы знать, когда пересылать сообщения вашему второму обработчику.

Например

private enum HandlerState { INITIAL, IMEI_RECEIVED; }
private HandlerState state = HandlerState.INITIAL;

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageList<Object> msgs) throws Exception
{

    if (state == HandlerState.INITIAL)
    {
        MessageList<String> imeis = msgs.cast();
        String imei = imeis.get(0);

        ctx.write(Constants.BUS_DATA_ACCEPT);
        state = HandlerState.IMEI_RECEIVED;
    } else
    {
        // Forward message to next handler...
        // Not sure exactly how this is done in Netty 4
        // Maybe: ctx.fireMessageReceived(msgs);
        // Or maybe it is:
        // ctx.nextInboundMessageBuffer().add(msg);
        // ctx.fireInboundBufferUpdated();

        // I believe you could also remove the IMEI handler from the
        // pipeline instead of having it keep state, if it is not going to do anything
        // further.
    }

}

Так что либо отслеживайте состояние в обработчике, либо удалите обработчик из конвейера после его завершения, если он не будет использоваться в дальнейшем. При отслеживании состояния вы можете либо сохранить состояние в самом обработчике (как показано выше), либо оставить переменные состояния в карте контекста / атрибута (как это делается в netty 4).

Причина, по которой вы не сохраняете состояние в самом обработчике, может заключаться в том, что вы собираетесь сделать обработчик доступным (один экземпляр используется для нескольких каналов). В этом нет необходимости, но может быть некоторая экономия ресурсов, если у вас большое количество одновременных каналов.

Другие вопросы по тегам