1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | io.netty.handler.codec.TooLongFrameException: Adjusted frame length exceeds 1048576: 2901213193 - discarded at io.netty.handler.codec.LengthFieldBasedFrameDecoder.fail(LengthFieldBasedFrameDecoder.java:493) at io.netty.handler.codec.LengthFieldBasedFrameDecoder.failIfNecessary(LengthFieldBasedFrameDecoder.java:469) at io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:404) at io.netty.handler.codec.serialization.ObjectDecoder.decode(ObjectDecoder.java:68) at io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:351) at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:231) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:131) at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:372) at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:780) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:99) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:497) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:465) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:359) at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101) at java.lang.Thread.run(Thread.java:745) |
Here is the client:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import java.io.ObjectOutputStream; import java.net.Socket; public class RowSocketClient { public static void main(String[] args) throws Exception { String host = "localhost"; int port = 4446; try (Socket socket = new Socket(host, port); ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream())) { out.writeObject("ping"); } } } |
Here is the server:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.serialization.ClassResolvers; import io.netty.handler.codec.serialization.ObjectDecoder; import java.net.InetSocketAddress; public class NettySocketServer { public static void main(String[] args) throws Exception { int port = 4446; EventLoopGroup group = new NioEventLoopGroup(); try { ServerBootstrap boot = new ServerBootstrap(); boot.group(group) .channel(NioServerSocketChannel.class) .localAddress(new InetSocketAddress(port)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast( new ObjectDecoder(ClassResolvers.cacheDisabled(null)), new RowSocketObjectDecoder()); } }); ChannelFuture future = boot.bind().sync(); System.out.println(NettySocketServer.class.getName() + " started and listens on " + future.channel().localAddress()); future.channel().closeFuture().sync(); } finally { group.shutdownGracefully().sync(); } } private static class RowSocketObjectDecoder extends SimpleChannelInboundHandler<String> { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println(msg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } } |
The purpose was to use Netty server with a not-Netty client to receive the objects. But it didn’t work and here’s why:
io.netty.handler.codec.serialization.ObjectDecoder
A decoder which deserializes the received ByteBufs into Java objects.
Please note that the serialized form this decoder expects is not compatible with the standard ObjectOutputStream. Please use ObjectEncoder or ObjectEncoderOutputStream to ensure the interoperability with this decoder.
Here’s the updated version of the client which works with ObjectDecoder:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import io.netty.handler.codec.serialization.ObjectEncoderOutputStream; import java.net.Socket; public class UpdatedRowSocketClient { public static void main(String[] args) throws Exception { String host = "localhost"; int port = 4446; try (Socket socket = new Socket(host, port); ObjectEncoderOutputStream outEncoder = new ObjectEncoderOutputStream(socket.getOutputStream())) { outEncoder.writeObject("ping"); } } } |
And the output from the server:
1 2 | com.github.rd.netty.test.NettySocketServer started and listens on /0:0:0:0:0:0:0:0:4446 ping |
It works but it is not what I was looking for. What if we don’t have an access to the client’s code and can’t modify it to meet the Netty’s server requirements for encoding/decoding java objects. For example, log4j’s SocketAppender where the client is a log4j system which sends LoggingEvent objects via socket to all listening servers.
I found out that in Netty 3.x version there was a class which could solve my problem: CompatibleObjectDecoder. But it was deprecated and removed in 4.x version (which I use now). That was because of this critical bug: Deprecate CompatibleObjectDecoder.
Now it seems that Netty is incompatible with Java’s ObjectOutputStream/ObjectInputStream at all.
No comments:
Post a Comment