我遇到了一个问题,由于安全原因,我无法发布完整代码(抱歉)。我的问题的要点是我有一个ServerBootstrap,创建如下:
bossGroup = new NioEventLoopGroup();
workerGroup = new NioEventLoopGroup();
final ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addFirst("idleStateHandler", new IdleStateHandler(0, 0, 3000));
//Adds the MQTT encoder and decoder
ch.pipeline().addLast("decoder", new MyMessageDecoder());
ch.pipeline().addLast("encoder", new MyMessageEncoder());
ch.pipeline().addLast(createMyHandler());
}
}).option(ChannelOption.SO_BACKLOG, 128).option(ChannelOption.SO_REUSEADDR, true)
.option(ChannelOption.TCP_NODELAY, true)
.childOption(ChannelOption.SO_KEEPALIVE, true);
// Bind and start to accept incoming connections.
channelFuture = b.bind(listenAddress, listenPort);
使用createMyHandlerMethod()基本上返回ChannelInboundHandlerAdapter
的扩展实现
我还有一个&#34;客户&#34;侦听器,侦听传入的连接请求,并按如下方式加载:
final String host = getHost();
final int port = getPort();
nioEventLoopGroup = new NioEventLoopGroup();
bootStrap = new Bootstrap();
bootStrap.group(nioEventLoopGroup);
bootStrap.channel(NioSocketChannel.class);
bootStrap.option(ChannelOption.SO_KEEPALIVE, true);
bootStrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addFirst("idleStateHandler", new IdleStateHandler(0, 0, getKeepAliveInterval()));
ch.pipeline().addAfter("idleStateHandler", "idleEventHandler", new MoquetteIdleTimeoutHandler());
ch.pipeline().addLast("decoder", new MyMessageDecoder());
ch.pipeline().addLast("encoder", new MyMessageEncoder());
ch.pipeline().addLast(MyClientHandler.this);
}
})
.option(ChannelOption.SO_REUSEADDR, true)
.option(ChannelOption.TCP_NODELAY, true);
// Start the client.
try {
channelFuture = bootStrap.connect(host, port).sync();
} catch (InterruptedException e) {
throw new MyException(“Exception”, e);
}
MyClientHandler再次成为ChannelInboundHandlerAdapter的子类实例。一切正常,我收到来自&#34;服务器&#34;适配器,我处理它们,并在相同的上下文中发回它们。反之亦然#34;客户&#34;处理程序。
当我必须(对于某些消息)将它们从服务器或客户端处理程序代理到其他连接时,会发生问题。再一次,我很抱歉无法发布大量代码,但其中的主旨是我来自:
serverHandler.channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof myProxyingMessage) {
if (ctx.channel().isActive()) {
ctx.channel().writeAndFlush(someOtherMessage);
**getClientHandler().writeAndFlush(myProxyingMessage);**
}
}
}
现在问题在于:粗体(客户端)writeAndFlush - 从不实际写入消息字节,它不会抛出任何错误。 ChannelFuture返回所有false(成功,取消,完成)。如果我同步它,最终由于其他原因(我的代码中设置的连接超时)超时。
我知道我还没有发布我的所有代码,但我希望有人提供一些提示和/或指示,以解决为什么不写入客户端上下文的问题。我不是任何一个Netty专家,而且大部分代码都是由其他人编写的。它们都是ChannelInboundHandlerAdapter
如果您有任何问题,请随时提出任何问题。
***** EDIT ********* 我尝试使用以下测试代码将请求代理回不同的上下文/通道(即客户端通道):
public void proxyPubRec(int messageId) throws MQTTException {
logger.log(logLevel, "proxying PUBREC to context: " + debugContext());
PubRecMessage pubRecMessage = new PubRecMessage();
pubRecMessage.setMessageID(messageId);
pubRecMessage.setRemainingLength(2);
logger.log(logLevel, "pipeline writable flag: " + ctx.pipeline().channel().isWritable());
MyMQTTEncoder encoder = new MyMQTTEncoder();
ByteBuf buff = null;
try {
buff = encoder.encode(pubRecMessage);
ctx.channel().writeAndFlush(buff);
} catch (Throwable t) {
logger.log(Level.SEVERE, "unable to encode PUBREC");
} finally {
if (buff != null) {
buff.release();
}
}
}
public class MyMQTTEncoder extends MQTTEncoder {
public ByteBuf encode(AbstractMessage msg) {
PooledByteBufAllocator allocator = new PooledByteBufAllocator();
ByteBuf buf = allocator.buffer();
try {
super.encode(ctx, msg, buf);
} catch (Throwable t) {
logger.log(Level.SEVERE, "unable to encode PUBREC, " + t.getMessage());
}
return buf;
}
}
但是上面的第ctx.channel().writeAndFlush(buff)
行不写入其他频道 - 调试此类问题的任何提示/技巧?
答案 0 :(得分:0)
someOtherMessage
必须为ByteBuf
。
所以,拿这个:
serverHandler.channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof myProxyingMessage) {
if (ctx.channel().isActive()) {
ctx.channel().writeAndFlush(someOtherMessage);
**getClientHandler().writeAndFlush(myProxyingMessage);**
}
}
}
...并将其替换为:
serverHandler.channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof myProxyingMessage) {
if (ctx.channel().isActive()) {
ctx.channel().writeAndFlush(ByteBuf);
**getClientHandler().writeAndFlush(myProxyingMessage);**
}
}
}
答案 1 :(得分:0)
实际上,这是一个线程问题。我的一个线程被阻塞/等待,而其他线程正在写入上下文,因此,即使使用刷新,写入也会被缓冲而不会被发送。问题解决了!
基本上,我将第一个消息代码放在Runnable / Executor线程中,这允许它单独运行,以便第二个写/响应能够写入上下文。这仍然存在一些问题(在消息排序方面),但这不是原始问题的主题。谢谢你的帮助!