使用Netty 4.0.27& Java 1.8.0_20
所以我试图通过构建一个简单的聊天服务器(典型的网络教程程序,我猜?)来了解Netty的工作原理。设计我自己的简单协议,称为ARC(安德鲁的中继聊天)...这就是为什么你在代码中看到ARC的原因很多。 K,所以这就是问题。
所以在这里我启动服务器并注册各种处理程序......
public void start()
{
System.out.println("Registering handlers...");
ArcServerInboundHandler inboundHandler = new ArcServerInboundHandler(this);
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try
{
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>()
{
@Override
public void initChannel(SocketChannel ch) throws Exception
{
ch.pipeline().addLast(new ArcDecoder(), inboundHandler);
ch.pipeline().addLast(new ArcEncoder());
}
}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);
try
{
System.out.println("Starting Arc Server on port " + port);
ChannelFuture f = bootstrap.bind(port).sync();
f.channel().closeFuture().sync();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
finally
{
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
当用户连接时,我的“inboundHandler”会被调用。
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception
{
System.out.println("CLIENT CONNECTED"); // THIS PRINTS, REACHES THIS POINT
ArcPacket packet = new ArcPacket();
packet.setArc("PUBLIC_KEY");
packet.setField("KEY", Crypto.bytesToHex(server.getRsaKeys().getPublic().getEncoded()));
ctx.writeAndFlush(packet);
}
这是我的编码器,不似乎完全被调用...
public class ArcEncoder extends MessageToByteEncoder<ArcPacket>
{
@Override
protected void encode(ChannelHandlerContext ctx, ArcPacket msg, ByteBuf out) throws Exception
{
System.out.println("ENCODE"); // NEVER GETS HERE
String message = ArcPacketFactory.encode(msg);
byte[] data = message.getBytes("UTF-8");
out.writeBytes(data);
System.out.println("WROTE");
}
@Override
public boolean acceptOutboundMessage(Object msg) throws Exception
{
System.out.println("ACCEPT OUTBOUND MESSAGE"); // NEVER GETS HERE
return msg instanceof ArcPacket;
}
}
所以,
调用ctx.writeAndFlush(packet)的代码;运行,但它似乎不会在任何时候调用编码器。我错过了一些明显的东西吗也许我正在添加错误的编码器?虽然我将它与我见过的其他例子进行比较时看起来很正确。
感谢您的帮助。
答案 0 :(得分:4)
您的编码器(ArcEncoder
)在入站处理程序后放置。这意味着,ctx.*()
方法调用永远不会被编码器评估。要解决您的问题,您必须在入站处理程序之前移动ArcEncoder
:
ch.pipeline().addLast(new ArcDecoder(), new ArcEncoder(), inboundHandler);
有关活动评估订单的更多信息,请阅读the API documentation of ChannelPipeline
。
答案 1 :(得分:2)
我认为问题在于您使用ChannelHandlerContext写入频道。这样做的目的是在处理程序的入口处将消息插入管道中。但是,由于您的解码器在管道中的编码器之前添加,这意味着您使用解码器上下文编写的任何内容都将在管道中的编码器之后插入。
确保编码器被调用的正确方法是调用:
ctx.channel.writeAndFlush()