クローラのような多くのサーバーに接続するクライアントを設計するとき。アプリケーション/ユーザーデータをChannelHandler Nettyに渡す方法
あなたはそのようなコードになります:あなたはApplicationHandler、あなたのSimpleChannelHandlerやWhatEverStreamHandlerを実装もの、(例でCrawlerHander)にあるとき今、あなたが得る唯一の情報がある
// the pipeline
public class CrawlerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new CrawlerHandler());
}
}
// the channel handler
public class CrawlerHandler extends SimpleChannelHandler {
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
// ...
}
}
// the main :
public static void main(){
ChannelFactory factory = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(),Executors.newCachedThreadPool());
ClientBootstrap scannerBootstrap = new ClientBootstrap(factory);
scannerBootstrap.setPipelineFactory(new CrawlerPipelineFactory());
while(true){
MyURL url = stack.pop();
ChannelFuture connect = scannerBootstrap.connect(url.getSocketAddress());
}
}
をsocketAdressあなたは "public void channelConnected()"関数でリカバリできることに接続しています。
しかし、コード例に表示されるMyURLオブジェクトのようなユーザーデータを回復したい場合はどうすればよいですか?
私は地図< "ip:port"、MyURL>を使用しているので、ip:port iが接続されていることを知っているので、channelConnectedの関連データを取得できます。
このハックは本当に汚いです。同じサーバーに同時に接続している場合(またはローカルポートにバインドして「localport:ip:remoteport」のようなキーを使用する必要がありますが、とても汚い)。
私は、データをCrawlerHanderに渡すための良い方法は何ですか?
このデータをブートストラップのconnect()メソッドで渡すことができれば、クールです。 ChannelPipelineFactory.getPipeline()は、connect()を介して呼び出されるため、引数を渡すことができます。しかし、今、私たちはそうここに私が使用して別の汚いハックです、することはできません。
EDIT:
// the main
while(!targets.isEmpty()){
client.connect("localhost",111); // we will never connect to localhost, it's a hack
}
// the pipleline
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new CrawlerHandler(targets.pop()) // I specify each new host to connect here
);
}
// in my channel handler
// Now I have the data I want in the constructor, so I m sure I get them before everything is called
public class CrawlerHandler extends SimpleChannelHandler {
ExtraParameter target;
public CrawlerHandler(ExtraParameter target) {
this.target = target;
// but, and it's the most dirty part, I have to abort the connection to localhost, and reinit a new connection to the real target
boolean bFirstConnect=true;
@Override
public void connectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
if(bFirstConnect){
bFirstConnect = false;
ctx.getChannel().connect(target.getSocketAddr());
}
あなたが話している同期の問題は何ですか?それをChannelPipelineFactoryに渡すと、atmに行くことができます。私はconnectメソッドで何らかのアタッチメントを渡すことができるようになる前に、ChannelPipeline.getPipeline()メソッドに自動的に渡されるというアイデアがあったと思います。しかし、私はそれについての電子メールをatm見つけることができませんでした。 –
ちょっとノーマン、あなたは良い方法であり、私がChannelPipelineFactory.getPipeline(Object theNewExtraParamater)経由で私のChannelHandler()のコンスータに渡すことができるように、connect()で添付ファイルを渡すことができれば、私の問題はすべて解決されます。 – Pierre
最後の文章は残念ですが同期問題ではありませんでした。私のもう1つの方法は汚れていて、編集した記事を見ています。コード例 – Pierre