2014-09-19 1 views
1

Я работаю над сервером приложений, часть которого будет основана на Netty 4.0. Однако я столкнулся с проблемой общих переменных для канала.
Я прочитал, что использовать такие переменные в других обработчиков контекстных мне нужно использоватьИспользование атрибутов каналов в обработчиках различных контекстов

  • context.channel(). Атр (ключ) .set()

вместо того, чтобы просто

  • context.attr (ключ) .set()

присоединить мои переменный текущий канал.
Как здесь:

public class HadlePackets extends ChannelInboundHandlerAdapter { 

private static final Logger LOG = LoggerFactory.getLogger(HadlePackets.class); 
public AttributeKey<Integer> clientIDattrKey = new AttributeKey<Integer> ("ClientID"); 

@Override 
public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception { 
... 
ctx.channel().attr(clientIDattrKey).set(IDnum); //bind ID to channel 

... 
} 
} 

Но, как я получить значение переменной в другом контексте обработчика? Ключ атрибута по-прежнему необходим, и я не могу его захватить у обработчика, который подключил переменную.

public class StorageHandler extends ChannelInboundHandlerAdapter{ 
private static final Logger LOG = LoggerFactory.getLogger(StorageSaveHandler.class); 

@Override 
public void channelInactive(ChannelHandlerContext ctx) throws Exception { 
    Integer clientID = (Integer)ctx.channel().attr(null).get(); //How can i get proper key for this channel attribute? 
    ctx.fireChannelInactive(); 

} 

ответ

3

это должно работать, так как это public static:

@Override 
public void channelInactive(ChannelHandlerContext ctx) throws Exception { 
    Integer clientID = (Integer) ctx.channel().attr(HandlePackets.clientIDattrKey).get(); 
    ctx.fireChannelInactive(); 
} 

Вот небольшой пример того, как я использую его. Это всего лишь фрагмент кода:

public class NettyServer implements Runnable { 
final static AttributeKey<Long> CHECKSUMKEY = AttributeKey.valueOf("calcchecksum"); 
final static AttributeKey<Command> COMMANDKEY = AttributeKey.valueOf("command"); 
final static AttributeKey<Long> FILEHANDLEKEY = AttributeKey.valueOf("filehandle"); 
final static AttributeKey<File> PATHKEY = AttributeKey.valueOf("destpath"); 
final static AttributeKey<FileOutputStream> OUTPUTSTREAM = AttributeKey.valueOf("stream"); 

@Override 
public void run() { 
    try { 
     EventLoopGroup bossGroup = new NioEventLoopGroup(BOSS_THREADS); 
     EventLoopGroup workerGroup = new NioEventLoopGroup(calculateThreadCount()); 
     try { 
      ServerBootstrap bootstrap = new ServerBootstrap(); 

      // This option will allow binding to an already bound ip:port 
      // combination. 
      // This is usually used to be able to restart a server if it 
      // crashed/got killed 
      // (so while the socket is still in the TIME_WAIT state). 
      bootstrap.option(ChannelOption.SO_REUSEADDR, true); 
      bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() { 
       @Override 
       public void initChannel(SocketChannel ch) throws Exception { 
        ch.pipeline().addLast("ObjectDecoder", new ObjectDecoder(ClassResolvers.cacheDisabled(null))); 
        ch.pipeline().addLast("ObjectEncoder", new ObjectEncoder()); 
        ch.pipeline().addLast("CommandHandler", new ServerCommandHandler(server, logger)); 
        ch.pipeline().addLast("FileHandler", new ServerFileHandler(server, logger)); 
        ch.pipeline().addLast("ChecksumHandler", new ServerChecksumHandler(server, logger)); 
       } 
      }); 

      try { 
       // Bind and start to accept incoming connections. 
       bootstrap.bind(port).sync().channel().closeFuture().sync(); 
      } catch (InterruptedException e) { 
       logger.debug(Message.CMDTRANSFER_INTERRUPTED_DEBUG, e.getMessage()); 
      } 
     } finally { 
      bossGroup.shutdownGracefully(); 
      workerGroup.shutdownGracefully(); 
     } 
    } catch (Exception e) { 
     logger.error(Message.CMDTRANSFER_CONNECT_ERROR, e.getMessage()); 
    } 
} 
} 

Как видите, у меня есть несколько обработчиков, которые разделяют атрибуты канала.

public class ServerCommandHandler extends ChannelInboundHandlerAdapter { 
    @Override 
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
     ctx.channel().attr(NettyServer.COMMANDKEY).set(clCommand); 
     ctx.fireChannelRead(msg); 
    } 
} 

public class ServerChecksumHandler extends ChannelInboundHandlerAdapter { 
    @Override 
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
     if ctx.channel().attr(NettyServer.COMMANDKEY).getAndRemove() == referenceCommand { 
      //do something 
     } 
    } 
} 
+0

Это действительно статично. Это была моя ошибка. Мне нужен уникальный идентификатор для каждого подключенного клиента, поэтому он не должен быть статическим. Но для каждого нового клиентского канала netty создаст новый экземпляр каждого ChanelContextHandler. Связаны ли они вокруг одного канала, и если я вызову обработчик A из обработчика B, он вызовет обработчик для того же канала, где будет обработчик B? – Asprelis

+0

нет, нет. это просто ключ, который статичен. Он может оставаться таким. У вас должен быть доступ к атрибуту, специфичному для канала, если вы установите его в свой метод channelRead (как и вы) и снова получите его в свой метод 'channelInactive' –

+0

отредактированный ответ и добавленный пример. –

Смежные вопросы