我最近开始将netty用于我的项目。我实现了HexDumpProxy示例,以了解netty的工作原理。当我在通道管道中添加StringDecoder和StringEncoder导致管道损坏时,我遇到了问题。如果解码器/编码器不存在,则程序按预期工作。有人能解释我为什么会这样吗?任何帮助都非常感谢!
我正在添加代码。
主要课程:
public final class HexDumpProxy {
public static void main(String[] args) throws Exception {
// Configure the bootstrap.
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 HexDumpProxyInitializer("127.0.0.1", 9000))
.childOption(ChannelOption.AUTO_READ, false)
.bind(8000).sync().channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
初始化程序类:
public class HexDumpProxyInitializer extends ChannelInitializer<SocketChannel> {
private final String remoteHost;
private final int remotePort;
public HexDumpProxyInitializer (String remoteHost, int remotePort) {
this.remoteHost = remoteHost;
this.remotePort = remotePort;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("frameDecoder", new LineBasedFrameDecoder(80));
ch.pipeline().addLast("decoder", new StringDecoder());
ch.pipeline().addLast("encoder", new StringEncoder());
//ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO));
ch.pipeline().addLast(new HexDumpProxyFrontendHandler(remoteHost, remotePort));
}
}
前端处理程序类:
public class HexDumpProxyFrontendHandler extends ChannelInboundHandlerAdapter {
private final String remoteHost;
private final int remotePort;
private Channel serverChannel;
public HexDumpProxyFrontendHandler(String remoteHost, int remotePort) {
this.remoteHost = remoteHost;
this.remotePort = remotePort;
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
final Channel clientChannel = ctx.channel();
Bootstrap b = new Bootstrap();
b.group(clientChannel.eventLoop())
.channel(ctx.channel().getClass())
.handler(new HexDumpProxyBackendHandler(clientChannel))
.option(ChannelOption.AUTO_READ, false);
ChannelFuture f = b.connect(remoteHost, remotePort);
serverChannel = f.channel();
f.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
clientChannel.read();
}
else
clientChannel.close();
}
});
}
@Override
public void channelRead (final ChannelHandlerContext ctx, Object msg) {
if (serverChannel.isActive()) {
System.out.println("************" + msg);
serverChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
ctx.channel().read();
System.out.println("Read from server channel. - channelRead");
} else {
future.channel().close();
System.out.println("Close server channel.");
}
}
});
}
}
@Override
public void channelInactive (ChannelHandlerContext ctx) {
if (serverChannel != null) {
closeOnFlush(serverChannel);
System.out.println("close on flush - server channel");
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
static void closeOnFlush (Channel ch) {
if (ch.isActive())
ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
ctx.channel().read();
}
}
Backend Handler类:
public class HexDumpProxyBackendHandler extends ChannelInboundHandlerAdapter {
private final Channel clientChannel;
public HexDumpProxyBackendHandler (Channel clientChannel) {
this.clientChannel = clientChannel;
}
@Override
public void channelActive (ChannelHandlerContext ctx) {
ctx.channel().read();
System.out.println("Read from client channel. - channelActive");
}
@Override
public void channelRead (final ChannelHandlerContext ctx, Object msg) {
System.out.println("~~~~~~~~~~~" + msg);
clientChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
clientChannel.read();
System.out.println("Read from client channel. - channelRead");
} else {
clientChannel.close();
System.out.println("Close client channel.");
}
}
});
}
@Override
public void channelInactive (ChannelHandlerContext ctx) {
HexDumpProxyFrontendHandler.closeOnFlush(clientChannel);
System.out.println("close on flush - client channel");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
ctx.channel().read();
}
}
答案 0 :(得分:0)
对于将来会遇到类似问题的每个人,我发现了问题所在。
在类HexDumpProxyFrontendHandler
中,而不是在引导期间使用新的HexDumpProxyBackendHandler(clientChannel)
作为处理程序,创建一个新类,例如HexDumpProxyBackendInitializer(clientChannel)
并在类中以与类HexDumpProxyInitializer
中相同的方式初始化管道。
希望这可以帮助别人!