全身、こんにちは!netty:なぜハンドラのコードでfuture.await()を使用できないのですか?
netty 3.1を使用してソケットデータを別のソケットサーバーに転送するソケットディスパッチサーバーを構築するため、次のmessageRecvイベントが到着したときに最初のメッセージが到着したときにnettyサーバーハンドラでクライアント接続を作成し、 、私はバッファをサーバーチャネルからクライアントチャネルに転送するだけです。しかしfuture.await *()操作を使用するときはハンドラで禁止されています。 await()を使わないと、connectFutureが同期しているので、次のメッセージが到着したときにconenctが完了していない可能性があります。私はこの問題をどう対処するかを知らない。
次のmessageRecvイベントが到着する前にクライアントの接続が完了していることを確認するにはどうすればよいですか?今
、私はちょうどこのように、2つのコードを同期するためのロックを行います。
/**
* 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();
}
}
}
はどうもありがとうございました、私はあなたの第二の溶液を選択しますが、機能inboundChannel.setReadable(false)を見つけます。非同期であり、返されたchannelFuture beanは、それ自体に追加されたlistnerを呼び出さないようです。 – xinglu
私はnetty 3.1コード、クラスorg.jboss.netty.channel.socket.nio.NioWorker行659行に "void setInterestOps( NioSocketChannel channel、ChannelFuture future、int interestOps)関数でステップします"キー== nullまたはセレクターがnullの場合、関数は単に戻り値であり、将来の状態は設定されません。真実を伝えるために、私はもうnettyコアコードを捕まえません。しかし、私は "inboundChannel.setReadable(false)"の設定操作は単に関数の呼び出しではなく、非同期ではないと思います。私はあなたからの2番目のソリューションを使用することが安全だと思う、ありがとう! – xinglu
申し訳ありませんあなたの問題を理解できません..詳細を教えてください。 –