2012-07-11 146 views
2

我设立使用OioClientSocketChannelFactory和 管道这样的客户端连接:Netty的阻断客户端

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)发送关于连接(SimpleChannelHandler.channelConnected)握手消息,和有责任从服务器使用握手回复(SimpleChannelHandler.messageReceived),而不将它传递给管道。我不希望API的用户接收某些低级消息,这是FooClientManager的责任。

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

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

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

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

回答

1

当握手完成时,FooClientManager需要通知API用户。一种选择是让API用户实现一个传入FooClientManager构造函数的接口。您始终可以创建此接口的默认实现,它的行为类似于未来,并允许API用户在握手完成之前阻止。

另一种选择是让FooClientManager在流水线上发送自定义消息,通知连接已准备就绪。然后API用户在reader.read()上阻塞,直到它接收到消息。

0

感谢您的答案johnstlr!

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

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

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

我很高兴您找到了解决方案。另一个提示是,你也可以使用org.jboss.netty.channel.Channels.write(...)直接向管道中的下一个处理程序写入消息。 – johnstlr 2012-07-13 08:02:42