java - Netty 4在处理程序中多次读/写

标签 java networking netty

我是 Netty 的新手,我决定从 4.0.0 开始,因为我认为它应该更好,因为它更新。我的服务器应用程序应该从 gps 设备接收数据,过程是这样的 - 首先我接收 2 个字节,这是设备 imei 的长度,然后我接收该长度的 imei,然后我应该发送 0x01 到设备,如果我想接受来自它的数据。在我的应答设备通过 AVL 协议(protocol)向我发送 GPS 数据后。现在我的服务器在没有 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 来做到这一点,对此我也将感激不已。

最佳答案

我没有使用过 Netty 4,所以我不确定我的答案是否 100% 准确,或者是在 Netty 4 中执行操作的最佳方法,但您需要做的是跟踪连接/客户端 session 的状态以便知道何时将消息转发给您的第二个处理程序。

例如

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 中完成的)。

不将状态保留在处理程序本身中的原因是如果您打算使处理程序可共享(跨多个 channel 使用一个实例)。没有必要这样做,但如果您有大量并发 channel ,可能会节省一些资源。

关于java - Netty 4在处理程序中多次读/写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17455510/

相关文章:

java - 用于输入文本文件的 DataInputStream?

java - 为什么这个 lambda 不是一个单一对象?

networking - PING 使用哪些协议(protocol)?

java - Jboss Netty - 无法连续发送数据?

java - 在读取超时时写入 channel

java.net.MalformedURLException : no protocol:

java - 将 ArrayList 从 SecondActivity 传递到 MainActivity Android

c - 如何重新加载系统守护进程?

networking - 为什么socks5协议(protocol)的服务器回复可以使用虚拟值?

java - decode() 没有读取任何内容,但解码了一条消息