Нетти 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).
Причина, по которой вы не сохраняете состояние в самом обработчике, может заключаться в том, что вы собираетесь сделать обработчик доступным (один экземпляр используется для нескольких каналов). В этом нет необходимости, но может быть некоторая экономия ресурсов, если у вас большое количество одновременных каналов.