Java 在netty中汇集客户端通道的正确方法?

Java 在netty中汇集客户端通道的正确方法?,java,netty,Java,Netty,我在下面的代码中得到一个java.nio.channels.NotYetConnectedException,因为我试图写入一个尚未打开的通道 基本上,我拥有的是一个通道池,在其中,如果一个通道空闲,我将获取一个要写入的通道,如果一个通道不可用,我将创建一个新的通道。我的问题是,当我创建一个新通道时,当我调用connect时,该通道还没有准备好写入,我不想在返回之前等待连接打开,因为我不想阻塞线程。最好的方法是什么?此外,我检索/返回通道的逻辑是否有效?请参阅下面的代码 我有一个简单的连接池,如

我在下面的代码中得到一个java.nio.channels.NotYetConnectedException,因为我试图写入一个尚未打开的通道

基本上,我拥有的是一个通道池,在其中,如果一个通道空闲,我将获取一个要写入的通道,如果一个通道不可用,我将创建一个新的通道。我的问题是,当我创建一个新通道时,当我调用connect时,该通道还没有准备好写入,我不想在返回之前等待连接打开,因为我不想阻塞线程。最好的方法是什么?此外,我检索/返回通道的逻辑是否有效?请参阅下面的代码

我有一个简单的连接池,如下所示:

private static class ChannelPool {
    private final ClientBootstrap cb;
    private Set<Channel> activeChannels = new HashSet<Channel>();
    private Deque<Channel> freeChannels = new ArrayDeque<Channel>();
    public ChannelPool() {
        ChannelFactory clientFactory =
                new NioClientSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool());
        cb = new ClientBootstrap(clientFactory);
        cb.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() {
                return Channels.pipeline(
                        new HttpRequestEncoder(),
                        new HttpResponseDecoder(),
                        new ResponseHandler());
            }
        });
    }

    private Channel newChannel() {
        ChannelFuture cf;
        synchronized (cb) {
            cf = cb.connect(new InetSocketAddress("localhost", 18080));
        }
        final Channel ret = cf.getChannel();
        ret.getCloseFuture().addListener(new ChannelFutureListener() {

            @Override
            public void operationComplete(ChannelFuture arg0) throws Exception {
                System.out.println("channel closed?");
                synchronized (activeChannels) {
                    activeChannels.remove(ret);
                }
            }
        });
        synchronized (activeChannels) {
            activeChannels.add(ret);
        }
        System.out.println("returning new channel");
        return ret;
    }

    public Channel getFreeChannel() {
        synchronized (freeChannels) {
            while (!freeChannels.isEmpty()) {
                Channel ch = freeChannels.pollFirst();
                if (ch.isOpen()) {
                    return ch;
                }
            }
        }
        return newChannel();
    }

    public void returnChannel(Channel ch) {
        synchronized (freeChannels) {
            freeChannels.addLast(ch);
        }
    }
}

您必须向
bootstrap.connect(..)
返回的
ChannelFuture
添加一个侦听器,而不是在
bootstrap.connect(..)
之后立即将新频道添加到
activeChannels
,然后将频道添加到添加的侦听器中的
activeChannels
。这样,
getFreeChannel()
将永远无法获取尚未连接的通道


因为即使调用了
newChannel()
newChannel()
甚至在建立连接之前都会返回),
activeChannels
很可能是空的,所以您必须决定在这种情况下该怎么办。如果我是你,我会将
getFreeChannel()
的返回类型从
Channel
更改为
ChannelFuture
,以便在空闲频道准备就绪时通知调用者。

我想你不知道为什么我仍然得到“由对等方重置连接”(请参阅)。查看
private static class RequestHandler extends SimpleChannelHandler {

    @Override
    public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
        final HttpRequest request = (HttpRequest) e.getMessage();
        Channel proxyChannel = pool.getFreeChannel();
        proxyToClient.put(proxyChannel, e.getChannel());
        proxyChannel.write(request);
    }
}