Netty channelRead没有收到完整的消息

时间:2015-07-09 20:19:57

标签: java netty

为什么channelRead()没有给我发送给服务器的完整信息?当消息超过140字节(粗略地,有时更多,有时更少)时,有时会发生碎片。我使用NioServerSocketChannel类使用TCP套接字。

我使用4.1.0.Beta5。

当它到达时,是否有办法阅读完整的信息?

this.serverBootstrap = new ServerBootstrap();
this.serverBootstrap.group(new NioEventLoopGroup(1), new NioEventLoopGroup(6))
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>()
                {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception
                    {
                        ch.pipeline().addLast(new TestServerHandler());
                    }
                })
                .option(ChannelOption.SO_BACKLOG, (int)Short.MAX_VALUE)
                .option(ChannelOption.SO_RCVBUF, (int) Short.MAX_VALUE)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .option(ChannelOption.TCP_NODELAY, true);
this.serverBootstrap.bind(this.host, this.port);

类TestServerHandler扩展了ChannelInboundHandlerAdapter:

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {

        String s = buffer.toString(CharsetUtil.UTF_8);

        for(int i = 0; i < 20; i++)
        {
            s = s.replace("[" + ((char)i) + "]", i + "");
        }

        System.out.println(s.length() + "");
        System.out.println();
        System.out.println();
        System.out.println(s);
}

我需要一种方法来获取完整的bytebuf / bytearray,当它完全到达服务器并得到通知,这样我的应用程序就可以根据客户端发送的数据以正确的方式响应。

简而言之:我如何防止碎片并让channelRead事件输出整个消息/ bytebuf。

2 个答案:

答案 0 :(得分:5)

Netty使用的基本数据类型是Channel Buffers或ByteBuf。这只是一个字节集合而已。在您的代码中,您只需使用自定义处理程序来处理原始传入数据。这通常不是一个好习惯。一个非常基本的netty管道应该类似于以下

enter image description here

因此,管道由解码器/编码器组成,然后我们有自定义处理程序或日志处理程序。我们从未真正处理任何原始数据。 TCP是一种流协议。它不会识别特定数据包何时结束并且新数据包开始。即使我们发送一个非常大的数据包或说两个单独的数据包,它们也只会被视为一组字节,当我们尝试读取原始字节集时,可能会发生碎片

正确实现一个由字符串解码器/编码器(无论你需要什么)组成的通道管道,这个问题就会消失。

答案 1 :(得分:1)

TCP提供了一个字节流,因此您不能依赖于在一个数据包中接收完整的消息。您需要一个管道中的处理程序,它知道您的消息是如何构建的。 Netty提供了一些内置处理程序,您可以根据协议进行调整。请参阅Netty用户指南中的Dealing with a Stream-based Transport