Sockets 从不同的InboundChannelHandlerAdapter.channelRead调用writeAndFlush时出现问题
我有一个问题,由于安全原因,我无法发布完整的代码。我的问题的要点是我有一个ServerBootstrap,创建如下:Sockets 从不同的InboundChannelHandlerAdapter.channelRead调用writeAndFlush时出现问题,sockets,io,netty,Sockets,Io,Netty,我有一个问题,由于安全原因,我无法发布完整的代码。我的问题的要点是我有一个ServerBootstrap,创建如下: bossGroup = new NioEventLoopGroup(); workerGroup = new NioEventLoopGroup(); final ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.c
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);
其中MyClientHandler又是ChannelInboundHandlerAdapter的子类实例。一切正常,我收到来自服务器适配器的消息,我处理它们,然后将它们发送回相同的上下文。对于客户端处理程序,反之亦然
当我必须将某些消息从服务器或客户端处理程序代理到其他连接时,就会出现问题。再一次,我很抱歉不能发布太多代码,但我的主旨是:
serverHandler.channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof myProxyingMessage) {
if (ctx.channel().isActive()) {
ctx.channel().writeAndFlush(someOtherMessage);
**getClientHandler().writeAndFlush(myProxyingMessage);**
}
}
}
现在问题来了:粗体的客户机writeAndFlush从未实际写入消息字节,它不会抛出任何错误。ChannelFuture返回所有错误的成功、取消、完成。如果我在上面同步,它最终会因为代码中设置的连接超时的其他原因超时
我知道我还没有发布所有的代码,但我希望有人能提供一些提示和/或指针,帮助解决为什么不向客户机上下文写入代码的问题。我并不是一个多愁善感的专家,这段代码大部分是由别人写的。它们都是ChannelInboundHandlerAdapter的子类
如果有任何问题,请随时提问
*****编辑*********
我尝试使用以下测试代码将请求代理回不同的上下文/通道,即客户端通道:
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.writeAndFlushbuff没有向另一个通道写入-有没有关于调试此类问题的提示/技巧 其他消息必须是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);**
}
}
}
实际上,这是一个线程问题。我的一个线程被阻塞/等待,而其他线程正在向上下文写入,因此,写入被缓冲,而不被发送,即使是刷新。问题解决了
本质上,我将第一条消息代码放在一个可运行/执行器线程中,这允许它单独运行,以便第二次写入/响应能够写入上下文。在消息排序方面,这仍然存在一些潜在的问题,但这不是原始问题的主题。谢谢你的帮助 谢谢你的评论。我相信在这种情况下,实际上并不需要ByteBuf,因为我有一个负责字节处理的解码器/编码器。例如,MQTTDecoder/MQTTEncoder。我不是100%确定,但这个问题似乎与netty处理通道读/写的方式有关——在这种情况下,我从服务器上下文中读取内容后,正在写入一个不同的上下文,而写入操作从不出于任何原因推送/刷新内容。我不知道为什么。我试过了-请看我上面的编辑-它不起作用:虽然我很有希望…你能提供你用来转换其他消息的ByteBuf代码吗?事实上,这是一个线程问题。我的一个线程被阻塞/等待,而其他线程正在向上下文写入,因此,写入被缓冲,而不被发送,即使是刷新。问题解决了!:
serverHandler.channelRead(ChannelHandlerContext ctx, Object msg) {
if (msg instanceof myProxyingMessage) {
if (ctx.channel().isActive()) {
ctx.channel().writeAndFlush(ByteBuf);
**getClientHandler().writeAndFlush(myProxyingMessage);**
}
}
}