Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将应用程序/用户数据传递给ChannelHandler Netty_Java_Netty - Fatal编程技术网

Java 如何将应用程序/用户数据传递给ChannelHandler Netty

Java 如何将应用程序/用户数据传递给ChannelHandler Netty,java,netty,Java,Netty,当你设计一个客户端,它将连接到很多服务器,比如一个爬虫 您将编写如下代码: // the pipeline public class CrawlerPipelineFactory implements ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception { return Channels.pipeline(new CrawlerHandler()); } }

当你设计一个客户端,它将连接到很多服务器,比如一个爬虫

您将编写如下代码:

// 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(示例中为CrawlerHandler)的东西,您得到的唯一一条信息是您正在连接的socketAddress,您可以在“public void channelConnected()”函数中恢复它

好的,但是如果我想恢复一些用户数据,比如您在我的代码示例中看到的MyURL对象,该怎么办

我使用一个肮脏的黑客,我使用一个映射,这样我就可以在channelConnected中检索相关数据,因为我知道我连接的ip:port

这种攻击非常肮脏,如果您同时连接到同一台服务器(或者您必须绑定到本地端口并使用类似“localport:ip:remoteport”的密钥,但它太脏了),它就不起作用了

所以我在寻找什么是向CrawlerHander传递数据的好方法

如果我们可以通过引导的connect()方法传递这些数据,那就太酷了。我知道我可以在ChannelPipelineFactory.getPipeline()中传递参数,因为它是通过connect()调用的。但现在我们不能,所以这里是我使用的另一个肮脏的黑客:

编辑:


您可以使用ChannelLocal或在ChannelHandlerContext中(或在最新Netty 3.x中的通道中)使用connect future侦听器将数据传递给新连接的通道/通道处理程序。在下面的示例中,使用ChannelLocal

public class ChannelDataHolder {
  public final static ChannelLocal<String> CHANNEL_URL = new ChannelLocal<String>(true);
}

  // for each url in bootstrap

  MyURL url = ....; 
  ChannelFuture cf = scannerBootstrap.connect(url.getSocketAddress());

  final String urlString = url.getUrl();

  cf.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                ChannelDataHolder.CHANNEL_URL.set(future.getChannel(), urlString);
            }
   });



  //In the handler

 public class CrawlerHandler extends SimpleChannelHandler {
   @Override
   public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
      String urlString = ChannelDataHolder.CHANNEL_URL.get(ctx.getChannel()); 
      // ...use the data here
   }
 }
公共类ChannelDataHolder{
公共最终静态ChannelLocal\u URL=新ChannelLocal(真);
}
//对于引导中的每个url
我的url=。。。。;
ChannelFuture cf=scannerBootstrap.connect(url.getSocketAddress());
最后一个字符串urlString=url.getUrl();
cf.addListener(新的ChannelFutureListener(){
@凌驾
public void operation complete(ChannelFuture future)引发异常{
ChannelDataHolder.CHANNEL_URL.set(future.getChannel(),urlString);
}
});
//在处理程序中
公共类CrawlerHandler扩展了SimpleChannelHandler{
@凌驾
public void channelConnected(ChannelHandlerContext ctx、ChannelStateEvent e)引发异常{
String urlString=ChannelDataHolder.CHANNEL_URL.get(ctx.getChannel());
//…使用此处的数据
}
}
注意:您可以使用设置和获取数据,而不是ChannelLocal

  • ChannelHandlerContext.setAttachment()/getAttachment()

  • Netty最新3.x版本中的Channel.setAttachment()/getAttachment()


但是这两种方法都不支持类型安全。

您可以使用ChannelLocal或在ChannelHandlerContext中(或在最新的Netty 3.x中的通道中)使用connect future侦听器将数据传递给新连接的通道/通道处理程序。在下面的示例中,使用ChannelLocal

public class ChannelDataHolder {
  public final static ChannelLocal<String> CHANNEL_URL = new ChannelLocal<String>(true);
}

  // for each url in bootstrap

  MyURL url = ....; 
  ChannelFuture cf = scannerBootstrap.connect(url.getSocketAddress());

  final String urlString = url.getUrl();

  cf.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                ChannelDataHolder.CHANNEL_URL.set(future.getChannel(), urlString);
            }
   });



  //In the handler

 public class CrawlerHandler extends SimpleChannelHandler {
   @Override
   public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
      String urlString = ChannelDataHolder.CHANNEL_URL.get(ctx.getChannel()); 
      // ...use the data here
   }
 }
公共类ChannelDataHolder{
公共最终静态ChannelLocal\u URL=新ChannelLocal(真);
}
//对于引导中的每个url
我的url=。。。。;
ChannelFuture cf=scannerBootstrap.connect(url.getSocketAddress());
最后一个字符串urlString=url.getUrl();
cf.addListener(新的ChannelFutureListener(){
@凌驾
public void operation complete(ChannelFuture future)引发异常{
ChannelDataHolder.CHANNEL_URL.set(future.getChannel(),urlString);
}
});
//在处理程序中
公共类CrawlerHandler扩展了SimpleChannelHandler{
@凌驾
public void channelConnected(ChannelHandlerContext ctx、ChannelStateEvent e)引发异常{
String urlString=ChannelDataHolder.CHANNEL_URL.get(ctx.getChannel());
//…使用此处的数据
}
}
注意:您可以使用设置和获取数据,而不是ChannelLocal

  • ChannelHandlerContext.setAttachment()/getAttachment()

  • Netty最新3.x版本中的Channel.setAttachment()/getAttachment()


但这两种方法都不支持类型安全。

您可以通过引导将变量传递给通道

&


很晚才更新此答案。

您可以通过引导将变量传递到通道

&


很晚才更新此答案。

您正在谈论的同步问题是什么?把它交给ChannelPipelineFactory是去atm的方法。我想我们以前有过这样的想法,能够在connect方法中传递某种附件,然后自动传递给ChannelPipeline.getPipeline()方法。但是我没能在atm机上找到关于它的电子邮件。嗨,诺曼,你走得很好,如果我能在connect()中传递附件,那么我所有的问题都会得到解决,这样我就可以通过我的ChannelPipelineFactory.getPipeline(Object thenewextraparameter)将附件传递给我的ChannelHandler()的构造函数;很抱歉,我的最后几句话不是同步问题,这是因为我的另一个方法是去脏,看看编辑后的帖子,我添加了一个代码示例,如果你想看到一个同步问题示例,请阅读Jestan Nirojan的答案。你说的同步问题是什么?把它交给ChannelPipelineFactory是去atm的方法。我想我们以前有过这样的想法,能够在connect方法中传递某种附件,然后自动传递给ChannelPipeline.getPipeline()方法。但是我没能在atm机上找到关于它的电子邮件。嗨,诺曼,你走得很好,如果我能在connect()中传递附件,那么我所有的问题都会得到解决,这样我就可以通过我的ChannelPipelineFactory.getPipeline(Object thenewextraparameter)将附件传递给我的ChannelHandler()的构造函数;很抱歉我的最后几句话,这不是一个同步问题,因为我的另一个方法是去脏,看看编辑后的帖子,我添加了一个代码示例,如果你想看到一个同步问题示例,请阅读Jestan Nirojan的答案。很抱歉,这不是一个好的示例