我不知道该如何做到这一点,我认为我的做法是错误的 - 有人可以给我一个提示吗?
我已经使代理服务器与示例非常相似 HexDumpProxy。 目的不是为了转储流量,而是通过代理操纵数据解析,这部分工作正常。让我们称之为代理部分。
在同一个程序中,我启动第二个线程,使用另一个ServerBootstrap监听另一个端口,并且它有自己的eventloop等。当我在这个监听端口收到一些东西时,我想将这些数据发送到代理的一个通道部分我希望动态更改此频道。当我将数据发送到其中一个代理通道时,我收到此错误:
2013年4月29日10:05:10 PM BackendListenHandler exceptionCaught 警告:下游出现意外异常。 java.lang.IllegalStateException:从eventLoop外部调用的nextOutboundByteBuffer()
@Sharable
public class BackendListenHandler extends ChannelInboundByteHandlerAdapter {
private Channel outboundChannel;
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.read();
ctx.flush();
}
@Override
public void inboundBufferUpdated(final ChannelHandlerContext ctx, ByteBuf in) throws Exception {
outboundChannel = Proxy.connectionTable.frontendListenChannel;
if (!outboundChannel.isActive()) {
System.out.println("channel id=" + outboundChannel.id() + " is NOT active...");
} else if (outboundChannel.isActive()) {
ByteBuf out = outboundChannel.outboundByteBuffer();
out.writeBytes(in);
outboundChannel.flush().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
// was able to flush out data, start to read the next chunk
ctx.channel().read();
} else {
future.channel().close();
}
}
});
}
}
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (outboundChannel != null) {
closeOnFlush(outboundChannel);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.", cause);
ctx.close();
}
static void closeOnFlush(Channel ch) {
if (ch.isActive()) {
ch.flush().addListener(ChannelFutureListener.CLOSE);
}
}
}
为了测试,我保留并更改此静态变量中的代理通道:
Proxy.connectionTable.frontendListenChannel;
答案 0 :(得分:0)
在为“出站”连接创建Bootstrap时使用相同的EventLoop,如HexDump示例中所示。这将确保从相同的IO线程处理所有内容。 见[1]。
答案 1 :(得分:0)
而不是使用“outboundChannel.outboundByteBuffer()” - 我使用“Unpooled.copiedBuffer()”将字节写入另一个EventLoop的通道。
@Override
public void inboundBufferUpdated(final ChannelHandlerContext ctx, ByteBuf in) throws Exception {
outboundChannel = null;
if (Proxy.connectionTable.channelId != 0) {
outboundChannel = Proxy.allChannels.find(Proxy.connectionTable.channelId);
if (outboundChannel.isActive()) {
System.out.println("NOTIFY channel id=" + outboundChannel.id() + " is active...");
Rewrite rewrite = new Rewrite(byteBufConverter.byteBufToString(in), 2);
in.clear();
in = byteBufConverter.stringToByteBuf(rewrite.getFixedMessage());
outboundChannel.write(in);
outboundChannel.flush().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
ctx.channel().read();
} else {
future.channel().close();
}
}
});
}
}
}
其中“byteBufConverter.stringToByteBuf(rewrite.getFixedMessage())”返回“Unpooled.copiedBuffer(strFixed.getBytes())”