很遗憾,我不理解来自Netty服务器的输出:
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的服务器在某些方面收到了错误的数据,导致出现问题?
客户端代码:
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值相匹配。)
来自GUI客户端的方法(有点大,它是一个Netbeans Swing JFrame):
public void setTitle(Title title) {
this.title = title;
text.setText(title.toString());
}
以上方法的要点是将对象发送到GUI,然后相应地更新。同样地,我想触发更新或以其他方式将GUI连接到套接字I/O。
我真的不理解netty服务器的输出。服务器使用netty而客户端使用sockets是否有问题?两者都使用相同的POJO,具有serialVersionUID值。下面是netty handler代码:
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());
}
}
显然,在客户端连接后立即发生了一切崩溃,因此没有执行任何服务器处理程序代码。
服务器代码:
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();
}
}
}
[java] 2014年7月27日 上午9:25:02 net.bounceme.dur.netty.ServerHandler exceptionCaught [java] 信息: io.netty.handler.codec.TooLongFrameException: 调整后的帧长度超过1048576:2901213193 - 已丢弃
现在服务器上--所以,看起来更好了。谢谢。 - Thufir