Когда вы создаете клиента, который будет подключаться к большому количеству серверов, например, сканера.Как передать данные приложения/пользователя в ChannelHandler Netty
Вы закодировать что-то вроде этого:
// 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());
}
}
Теперь, когда вы находитесь в ApplicationHandler, материал, который реализует свой SimpleChannelHandler или WhatEverStreamHandler (CrawlerHander в примере) только часть информации, которую вы получаете является socketAdress, с которым вы подключаетесь, чтобы восстановить функцию «public void channelConnected()».
Хорошо, но что, если я хочу восстановить некоторые пользовательские данные, например объект MyURL, который вы видите в моем примере кода?
Я использую грязный хак, я использую карту < «ip: port», MyURL>, поэтому я могу получить связанные данные в channelConnected, потому что я знаю ip: порт, к которому я подключен.
Этот хак действительно грязный, он не будет работать, если вы одновременно подключаетесь к одному и тому же серверу (или вам придется привязываться к локальному порту и использовать такой ключ, как «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 - это путь к атм. Я думаю, у нас была идея, прежде чем иметь возможность передать какое-то вложение в методе connect, которое затем автоматически передается методу ChannelPipeline.getPipeline(). Но я не смог найти письмо об этом atm. –
Эй, Норман, вы на хорошем пути, вся моя проблема будет решена, если я смогу передать вложение в connect(), чтобы я мог передать ее консулатору ChannelHandler() через мою ChannelPipelineFactory.getPipeline (Object theNewExtraParamater); – Pierre
Извините, что мои последние предложения не были проблемой синхронизации, потому что мой другой метод - грязный, посмотрите на отредактированный пост, я добавил пример кода – Pierre