Netty阻止客户端

时间:2012-07-11 03:18:30

标签: netty

我正在使用OioClientSocketChannelFactory设置客户端连接 像这样的管道:

ClientBootstrap bootstrap = new ClientBootstrap(
    new OioClientSocketChannelFactory(Executors.newCachedThreadPool())
);

pipeline.addLast("encoder", new MessageEncoder());
pipeline.addLast("decoder", new MessageDecoder());
pipeline.addLast("manager", new FooClientManager());
BlockingReadHandler<Message> reader = new BlockingReadHandler<Message>();
pipeline.addLast("reader", reader);
bootstrap.setPipeline(pipeline);

FooClientManager类(SimpleChannelHandler)在connect(SimpleChannelHandler.channelConnected)上发送握手消息,并负责从服务器使用握手回复(SimpleChannelHandler.messageReceived)而不将其传递给管道。我不希望API的用户接收某些低级别消息,这是FooClientManager的消费责任。

预计在连接之后,API的用户现在将构造一条消息并调用channel.write()来发送消息,并调用reader.read()来阻止等待回复。

我遇到的问题是FooClientManager在API用户名为channel.write()之前没有看到握手回复,因为从未执行过read()。

如果我在调用channel.write()之前调用reader.read(),它会无限期地阻塞,因为FooClientManager不会发送消息我正试图读取管道。

处理可能消耗消息的管道中的客户端IO和通道处理程序的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

FooClientManager需要在握手完成时向API用户发出信号。一种选择是让API用户实现一个传递给FooClientManager构造函数的接口。您始终可以创建此接口的默认实现,其作用类似于未来,并允许API用户阻止,直到握手完成。

另一个选择是让FooClientManager在管道上发送自定义消息,表明连接已准备就绪。然后API用户在reader.read()上阻塞,直到收到消息为止。

答案 1 :(得分:0)

感谢你的回答johnstlr!

这两种解决方案都有效。我们实现的解决方案是在握手完成之前让FooClientManager队列写入请求。然后它发送所有排队的消息。

我们遇到的一个问题是,如果我们将所有写入请求排队直到握手完成,那么当FooClientManaager调用channel.write()并且消息通过整个管道发送时,握手消息本身就会排队。我们通过让FooClientManager构造一个消息事件并将其直接发送到管道中的下一个处理程序来解决这个问题:

ctx.sendDownstream(new DownstreamMessageEvent(ctx.getChannel(), new DefaultChannelFuture(ctx.getChannel(), false), msg, e.getChannel().getRemoteAddress()));