我使用netty 3.1来构建一个套接字调度服务器,它将套接字数据传输到另一个套接字服务器,所以当第一条消息到达时,我在netty服务器处理程序中创建一个客户端连接,等待单元连接完成,当下一个messageRecv事件到达时,我只是将缓冲区从服务器通道传输到客户端通道。但是我发现在使用future.await *()操作时禁止处理程序。如果我不使用await(),因为connectFuture是同步的,有可能在下一条消息到达时,但是conenct未完成。我不知道如何处理这个问题。
如何在下一个messageRecv事件到达之前确保客户端连接完成?
现在,我只是锁定同步两个代码,就像这样:
/**
* server handler
*/
public class ServerChannelHandler extends SimpleChannelUpstreamHandler {
private static Logger _logger = LoggerFactory.getLogger(cn.szboc.dispatch.server.netty.ServerChannelHandler.class);
public ServerChannelHandler(ProxyClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
/** factory connect another server */
private ProxyClientFactory clientFactory;
/** anotherchannel */
private Channel innerChannel;
private ChannelFuture connectFuture;
private ReentrantLock connectLock = new ReentrantLock();
private Condition notComplete = connectLock.newCondition();
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
final ChannelBuffer buffer = ((ChannelBuffer) e.getMessage()).copy();
final Channel outChannel = ctx.getChannel();
// first connect
if (connectFuture == null) {
final ClientChannelHandler cch = new ClientChannelHandler(ctx.getChannel());
ProxyClient client = clientFactory.retrieveClient();
connectFuture = client.getConnectChannelFuture();
connectFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
connectLock.lock();
try {
if (future.isSuccess()) {
innerChannel = future.getChannel();
innerChannel.getPipeline().addLast("clientchannelhandler", cch);
innerChannel.write(buffer);
} else {
Channels.fireExceptionCaught(outChannel, future.getCause());
}
} finally {
notComplete.signal();
connectLock.unlock();
}
}
});
} else {
connectLock.lock();
try {
if (!connectFuture.isDone()) {
if (!notComplete.await(500, TimeUnit.MILLISECONDS)) {
throw new Exception("");
}
}
if (connectFuture.isSuccess()) {
if(innerChannel == null){
if (!notComplete.await(500, TimeUnit.MILLISECONDS)) {
throw new Exception("");
}
}
innerChannel.write(buffer);
} else {
_logger.error("");
}
} finally {
connectLock.unlock();
}
}
}
答案 0 :(得分:1)
你不能,因为你可以使网络陷入僵局。你也会阻止IO-Worker线程,这是一件坏事。处理您的情况的最佳方法是“排队”消息,直到连接完成,然后分发它们。
另一种解决方案是在“channelOpen(..)”方法上连接到代理客户端,同时设置Channel.setReadable(false)。连接完成后,您将再次调用Channel.setReadable(true),以便处理messageEvents。
这样的事情:
@Override
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
// Suspend incoming traffic until connected to the remote host.
final Channel inboundChannel = e.getChannel();
inboundChannel.setReadable(false);
// Start the connection attempt.
ClientBootstrap cb = new ClientBootstrap(cf);
cb.getPipeline().addLast("handler", new OutboundHandler(e.getChannel()));
ChannelFuture f = cb.connect(new InetSocketAddress(remoteHost, remotePort));
outboundChannel = f.getChannel();
f.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
// Connection attempt succeeded:
// Begin to accept incoming traffic.
inboundChannel.setReadable(true);
} else {
// Close the connection if the connection attempt has failed.
inboundChannel.close();
}
}
});
}
有关更多详细信息,请参阅代理示例[1]。
[1] https://github.com/netty/netty/tree/3.2/src/main/java/org/jboss/netty/example/proxy