简体   繁体   中英

Java Netty - Send result to client as StringEncoder or ObjectEncoder depending on input message?

I'm new to Netty and so far there is a working client-server which can handle String message with StringEncoder and StringDecoder, eg:

        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup)
                       .channel(NioServerSocketChannel.class)
                       .handler(new LoggingHandler(LogLevel.TRACE))
                       .childHandler(new ChannelInitializer<SocketChannel>() {
                                            @Override
                                            public void initChannel(SocketChannel ch) throws Exception {
                                                ch.pipeline().addLast(
                                                    new LoggingHandler(LogLevel.TRACE),
                                                    new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Delimiters.lineDelimiter()),
                                                    new StringEncoder(),
                                                    new StringDecoder(),
                                                    new ReceiveMessageCommunicatorHandler(localNode, inpeerNodeRegistry, outpeerNodeRegistry));

The input message is just like this: excute_this and server sends back: ok .

Now, what I need to do is a server receives a new text message: get_object , it should send back to any client (eg: telnet or java application which uses the plain socket) a serialized object as byte array. Then in this client, it can deserialized this object as Java object.

I've known that ObjectEncoder() seems to be the way to do. But, it also serializes the response which should be String to a serialized object while it should do it for some specific messages (eg: get_object only).

How can I tell Netty when it should encode result as StringEncoder and when should encode as Serialized Object as byte array?

It is possible to dynamically modify the pipeline. When you receive get_object message you can simply remove the StringEncoder and add the ObjectEncoder in the relevant ChannelInboundHandler

   ChannelPipeline p = ctx.pipeline();
    if (p.get(StringEncoder.class) != null) {
        p.remove(StringEncoder.class);
    }
    p.addLast(new YourObjectEncoder())

Or if you know the name of your encoder you can do a replace:

p.replace("encoder", "encoder", new YourObjectEncoder());

Thanks for suggestion of Riyafa Abdul Hameed

It can switch Encoder dynamically as in this code when server received a message and writes response to client.

@Override
protected void channelRead0(ChannelHandlerContext ctx, String message) throws Exception {
    InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
    MessageContainer messageContainer = new MessageContainer(message, address);
    log.debug("\n");
    log.debug("Message received: {}", message);

    // Handle received message and write result back to the sender
    Object response = this.handleMessage(messageContainer);
    if (response instanceof String) {
        ctx.channel().pipeline().names();
        ctx.channel().pipeline().remove(ObjectEncoder.class);
        ctx.channel().pipeline().addFirst(new StringEncoder());
    }

    if (response != null) {
        ctx.write(response);
        ctx.flush();
    }
    ctx.close();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM