本文介绍了netty DefaultChannelPipeline异常已捕获的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不幸的是,我不明白来自Netty服务器的输出:

Unfortunately, I don't understand this output from the netty server:

BUILD SUCCESSFUL
Total time: 3 seconds
Jul 27, 2014 2:04:44 AM io.netty.handler.logging.LoggingHandler channelRegistered
INFO: [id: 0xcad25a31] REGISTERED
Jul 27, 2014 2:04:44 AM io.netty.handler.logging.LoggingHandler bind
INFO: [id: 0xcad25a31] BIND(0.0.0.0/0.0.0.0:4454)
Jul 27, 2014 2:04:44 AM io.netty.handler.logging.LoggingHandler channelActive
INFO: [id: 0xcad25a31, /0:0:0:0:0:0:0:0:4454] ACTIVE
Jul 27, 2014 2:04:59 AM io.netty.handler.logging.LoggingHandler logMessage
INFO: [id: 0xcad25a31, /0:0:0:0:0:0:0:0:4454] RECEIVED: [id: 0xff40b8a2, /127.0.0.1:37558 => /127.0.0.1:4454]
Jul 27, 2014 2:04:59 AM net.bounceme.dur.netty.ServerHandler <init>
INFO: starting..
Jul 27, 2014 2:04:59 AM io.netty.channel.DefaultChannelPipeline$TailContext exceptionCaught
WARNING: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.handler.codec.TooLongFrameException: Adjusted frame length exceeds 1048576: 2901213193 - discarded
    at io.netty.handler.codec.LengthFieldBasedFrameDecoder.fail(LengthFieldBasedFrameDecoder.java:501)
    at io.netty.handler.codec.LengthFieldBasedFrameDecoder.failIfNecessary(LengthFieldBasedFrameDecoder.java:477)
    at io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:403)
    at io.netty.handler.codec.serialization.ObjectDecoder.decode(ObjectDecoder.java:68)
    at io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:343)
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:241)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:149)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:333)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:319)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:787)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:125)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    at java.lang.Thread.run(Thread.java:744)

^Cthufir@dur:~/NetBeansProjects/AgentServer$ 
thufir@dur:~/NetBeansProjects/AgentServer$ 

大概是基于Netty的服务器在某些方面抱怨它接收到错误的数据吗?

Presumably the netty-based server is complaining that it's receiving bad data in some respect?

客户代码:

package net.bounceme.dur.client.gui;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import net.bounceme.dur.client.jdbc.Title;

public final class ApplicationDriver {

    private static final Logger log = Logger.getLogger(ApplicationDriver.class.getName());
    private TitlesGUI gui = null;
    private Handler handler = null;

    public ApplicationDriver() throws IOException, ClassNotFoundException {
        handler = new FileHandler("application.log");
        handler.setFormatter(new SimpleFormatter());
        log.setLevel(Level.INFO);
        log.addHandler(handler);
        log.info("starting log..");
        MyProps p = new MyProps();
        String host = p.getHost();
        int port = p.getServerPort();
        guiThread();
        readWrite(host, port);
    }

    private void guiThread() {
        Thread g;
        g = new Thread() {
            @Override
            public void run() {
                try {
                    gui = new TitlesGUI();
                } catch (IOException ex) {
                    log.severe(ex.toString());
                }
                gui.setVisible(true);
            }
        };
        g.start();
    }

    public static void main(String... args) throws IOException, ClassNotFoundException {
        new ApplicationDriver();
    }

    private void readWrite(final String host, final int port) throws IOException {
        Thread inputOutput;
        final Socket socket = new Socket(host, port);
        inputOutput = new Thread() {
            @Override
            public void run() {
                while (true) {
                    try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
                            ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream())) {
                        gui.setTitle((Title) objectInputStream.readObject());
                        Thread.sleep(1000);
                    } catch (IOException | ClassNotFoundException | InterruptedException ex) {
                        log.severe(ex.toString());
                    }
                }
            }

        };
        inputOutput.start();
    }
}

客户端使用常规套接字而不是netty是否存在问题?客户端和服务器端都正在发送POJO. (Title类是可序列化的,并且serialVersionUID值匹配.)

is it a problem that the client is using regular sockets instead of netty? Both on the client and server side POJO's are being sent. (The Title class is serializable and the serialVersionUID values match up.)

GUI客户端的方法(有点大,它是Netbeans Swing JFrame):

a method from the GUI client (which is a bit large, it's a Netbeans Swing JFrame):

public void setTitle(Title title) {
    this.title = title;
    text.setText(title.toString());
}

上述方法的目的是让 something 将对象发送到GUI,然后将其相应地更新.同样,我想触发更新,或者将GUI连接到套接字I/O.

the point of the above method is for something to send objects to the GUI, which is then updated accordingly. Similarly, I want to fire updates, or other-wise wire the GUI to socket i/o.

我不太了解Netty服务器的输出.服务器使用netty而客户端使用套接字是一个问题吗?两者都使用相同的POJO,并带有serialVersionUID值.这是净值处理程序代码:

I don't really understand the output from the netty server. Is it a problem that the server uses netty while the client uses sockets? Both use the same POJO, with the serialVersionUID value. Here's the netty handler code:

package net.bounceme.dur.netty;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.util.logging.Logger;
import net.bounceme.dur.jdbc.Title;

public class ServerHandler extends SimpleChannelInboundHandler<Title> {

    private static final Logger log = Logger.getLogger(ServerHandler.class.getName());

    public ServerHandler() {
        log.info("starting..");
    }

    @Override
    public boolean acceptInboundMessage(Object msg) throws Exception {
        log.info(msg.toString());
        return true;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.info(msg.toString());
        ctx.write(new Title());
    }

    @Override
    protected void channelRead0(ChannelHandlerContext chc, Title title) throws Exception {
        log.info(title.toString());
        chc.write(new Title());
    }
}

很明显,没有任何服务器处理程序代码被执行,因为在客户端连接后,所有内容都会立即爆炸.

Apparently, none of the server handler code is executed, as everything explodes immediately after the client connects.

服务器代码:

package net.bounceme.dur.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
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 io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import java.security.cert.CertificateException;
import java.util.logging.Logger;
import javax.net.ssl.SSLException;

public final class Server {

    private static final Logger log = Logger.getLogger(Server.class.getName());

    public static void main(String[] args) throws Exception {
        MyProps p = new MyProps();
        int port = p.getServerPort();
        new Server().startServer(port, false);
    }

    private void startServer(int port, boolean ssl) throws CertificateException, SSLException, InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline p = ch.pipeline();
                            p.addLast(
                                    new ObjectEncoder(),
                                    new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
                                    new ServerHandler());
                        }
                    });
            b.bind(port).sync().channel().closeFuture().sync();
            log.info("connected!");
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

推荐答案

LengthFieldBasedFrameDecoder引发的TooLongFrameException表示以下之一:

The TooLongFrameException raised by LengthFieldBasedFrameDecoder means one of the following:

  • 远程对等方发送了一条非常大的消息,该消息超出了限制.消息的默认最大长度为1 MiB.如果您希望收到一条大于该长度的消息,请在构造LengthFieldBasedFrameDecoder时指定其他最大长度.
  • 您将错误的参数传递给了LengthFieldBasedFrameDecoder,因此它正在解码消息中的错误位置.在这种情况下,您最好重新阅读LengthFieldBasedFrameDecoder的Javadoc以为您指定正确的值.
  • The remote peer sent a very large message, which exceeds the limit. The default maximum length of a message is 1 MiB. If you expect to receive a message larger than that, specify an alternative maximum length when you construct a LengthFieldBasedFrameDecoder.
  • You passed wrong parameters to LengthFieldBasedFrameDecoder so that it is decoding a wrong place in your message. In this case, you'd better re-read the Javadoc of LengthFieldBasedFrameDecoder to specify the correct values for you.

这篇关于netty DefaultChannelPipeline异常已捕获的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-14 15:59