【问题标题】:Sending and receiving ArrayList Objects or Array Objects in NettyNetty中收发ArrayList对象或Array对象
【发布时间】:2015-05-26 17:45:39
【问题描述】:

大家好,我是 netty 的新手。我想要的是这样的东西。在我的客户端上,我想输入一个字符串查询示例SELECT * FROM drivers。我正在使用 mysql xampp 服务器。然后我的服务器将查询它并将其添加到数组列表中

 private List<Drivers> getRecords(ResultSet rs) throws SQLException {

        List<Drivers> records = new ArrayList<Drivers>();
        while(rs.next()){
            records.add(new Drivers(rs.getInt("first_name"), rs.getString("last_name")));
        }
        return records;
    }

之后它会将 ArrayList 对象发送回客户端。

我现在的问题是如何将它填充到客户端

这是我的服务器管道

public class ServerInitializer extends ChannelInitializer<SocketChannel> {

    private final SslContext sslCtx;

    public ServerInitializer(SslContext sslCtx) {
        this.sslCtx = sslCtx;
    }

    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        // Add SSL handler first to encrypt and decrypt everything.
        // In this example, we use a bogus certificate in the server side
        // and accept any invalid certificates in the client side.
        // You will need something more complicated to identify both
        // and server in the real world.
        pipeline.addLast(sslCtx.newHandler(ch.alloc()));

        // On top of the SSL handler, add the text line codec.
        /*
        pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        pipeline.addLast(new StringDecoder());
        pipeline.addLast(new StringEncoder());
          */
        //pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        /*

        */
        //pipeline.addLast("frameDecoder",new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));
        //pipeline.addLast("bytesDecoder",new ByteArrayDecoder());
        pipeline.addLast(new ObjectEncoder());
        pipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));

        // and then business logic.
        pipeline.addLast(new ServerHandler());
    }
}

我的客户管道

 public class ClientInitializer extends ChannelInitializer<SocketChannel> {

        private final SslContext sslCtx;

        public ClientInitializer(SslContext sslCtx) {
            this.sslCtx = sslCtx;
        }

        @Override
        public void initChannel(SocketChannel ch) throws Exception {
            ChannelPipeline pipeline = ch.pipeline();

            // Add SSL handler first to encrypt and decrypt everything.
            // In this example, we use a bogus certificate in the server side
            // and accept any invalid certificates in the client side.
            // You will need something more complicated to identify both
            // and server in the real world.
            pipeline.addLast(sslCtx.newHandler(ch.alloc(), Client.HOST, Client.PORT));

            // On top of the SSL handler, add the text line codec.

            /*
            pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
            pipeline.addLast(new StringDecoder());
            pipeline.addLast(new StringEncoder());
              */
            //pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
            /*
            */
            pipeline.addLast("frameDecoder",new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4));
            pipeline.addLast("bytesDecoder",new ByteArrayDecoder());
            pipeline.addLast(new ObjectEncoder());
            pipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
            // and then business logic.
            pipeline.addLast(new ClientHandler());
        }
    }

我的服务器通道处理程序

public class ServerHandler extends ChannelInboundHandlerAdapter {

    static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    @Override
    public void channelActive(final ChannelHandlerContext ctx) {
        // Once session is secured, send a greeting and register the channel to the global channel
        // list so the channel received the messages from others.
        ctx.pipeline().get(SslHandler.class).handshakeFuture().addListener(
                new GenericFutureListener<Future<Channel>>() {
                    @Override
                    public void operationComplete(Future<Channel> future) throws Exception {

                        channels.add(ctx.channel());
                    }
        });
    }

    private List<Drivers> getRecords(ResultSet rs) throws SQLException {

        List<Drivers> records=new ArrayList<Drivers>();
        while(rs.next()){
            records.add(new Drivers(rs.getInt(0), rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), 
                    rs.getString(5), rs.getString(6), rs.getInt(7), rs.getString(8), rs.getString(9), rs.getString(10), 
                    rs.getString(11), rs.getString(12), rs.getString(13), rs.getString(14), 
                    rs.getString(15), rs.getString(16), rs.getString(17), rs.getString(18), rs.getString(19)));
        }
        return records;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
    {
         // Send the received message to all channels but the current one.
        for (Channel c: channels) {
            if (c != ctx.channel()) {
                c.writeAndFlush("[" + ctx.channel().remoteAddress() + "] " + msg + '\n');

            } else {

                try {
                    new DataManipulator();
                    System.out.print(msg.toString());
                    ResultSet rs = DataManipulator.generalQuery(msg.toString());
                    c.writeAndFlush(getRecords(rs));

                } catch (ClassNotFoundException | InstantiationException
                        | IllegalAccessException | SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

        // Close the connection if the client has sent 'bye'.
        if ("bye".equals(msg.toString().toLowerCase())) {
            ctx.close();
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

我的客户频道处理程序

public class ClientHandler extends SimpleChannelInboundHandler<Object[]> {

     static int count = 1;
     @Override
     public void channelActive(final ChannelHandlerContext ctx) {
         System.out.println(ctx.read());
     }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object[] msg)
            throws Exception {
        // Still don't know how to receive the data.

    }
}

请帮助如何在 netty 上完美地做到这一点。

【问题讨论】:

    标签: java mysql arraylist netty


    【解决方案1】:

    您的管道中不需要ByteArrayDecoderLengthFieldBasedFrameDecoder。你需要的是ObjectDecoderObjectEncoder,这应该是全部(除了你的最后一个处理程序。)

    【讨论】:

    • 很高兴得到netty创作者的回答。我会试试看。我现在的问题是如何在我的客户端上填充 Array。我的意思是如何在客户端提取数组。我尝试使用以下
    • ClientHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, Object[] msg) throws Exception { /// 在此处提取 Object[] msg,但是如何? /// 我试图输出。 System.out.println(msg); // 无输出 } }
    • ClientHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { /// 在这里提取 Object msg,但是如何? /// 我试图输出。 System.out.println(msg); // 无输出 } }
    • 有什么想法吗?怎么办?
    【解决方案2】:

    我碰巧用一个小技巧解决了这个问题。 在您的情况下,我认为以下示例代码可能会有所帮助。

    通过定义一个 NettyMessage

    public class NettyMessage implements Serializable{
    
        private static final long serialVersionUID = 1L;
        private  String action;
        private  List<Drivers> body;
        // getter and setter....
    

    ServerHandler内,

    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        List<Drivers> list = c.writeAndFlush(getRecords(rs));
        ctx.writeAndFlush(new NettyMessage("myaction", list));
    }
    

    ClientHandler内,

    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        NettyMessage message = (NettyMessage)msg;
        List<Drivers> driverList = message.getBody();
    }
    

    但不要扩展 SimpleChannelInboundHandler

    【讨论】:

    • 非常感谢。我会试试看。但是为什么我在构造函数中需要那个动作参数呢?
    • "but don't extends SimpleChannelInboundHandler" 你的意思是我只会使用 ChannelInboundHandlerAdapter?
    • @Yves Gonzaga 如果您扩展 SimpleChannelInboundHandler,您将不会覆盖 channelRead 方法。您可能已经尝试过扩展 ChannelInboundHandlerAdapter。动作参数不是必需的,但不知何故我在工作中使用它来过滤传入的消息,我只是把它留在这里以防你也需要它。
    • 我尝试使用您的方法。但是,当我尝试迭代到 arraylist 时,它不会输出任何内容。管道解码和编码有什么我想念的吗? NettyMessage 消息 = (NettyMessage)msg; ArrayList driverList = (ArrayList) message.getBody();迭代器 itr = driverList.iterator(); for(驱动程序驱动程序:driverList){ System.out.println(drivers.getFirstName()); }
    • 我用这两个,ch.pipeline().addLast(new ObjectDecoder(1024, ClassResolvers.cacheDisabled(this.getClass().getClassLoader()))); ch.pipeline().addLast(new ObjectEncoder());
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 2015-07-30
    • 1970-01-01
    • 2021-03-11
    • 2018-03-27
    • 1970-01-01
    相关资源
    最近更新 更多