2014-11-21 17 views
5

Tôi đang cố gắng truy cập vào Netty bằng ứng dụng máy khách-ứng dụng đơn giản (xem mã bên dưới).Netty Handler không được gọi là

Tôi đang phải vật lộn với hai vấn đề:

  1. các ConfigServerHandler resp. ConfigClientHandler được gọi chính xác. Nhưng RespServerHandler resp. FeedbackClientHandler không bao giờ được gọi. Tại sao? Theo tài liệu, các trình xử lý nên được gọi là cái khác.

  2. Tôi muốn có một số trình xử lý. Mỗi trình xử lý này chỉ quan tâm đến một số thông điệp được gửi ở phía bên kia (ví dụ: gửi bởi máy khách, được máy chủ nhận).

    • Tôi có nên lọc các thư sau khi chúng đã được một trình xử lý (channelRead) nhận không? Làm thế nào tôi có thể phân biệt các chuỗi khác nhau? Với các đối tượng khác nhau, điều này sẽ khá dễ dàng bằng cách phân tích chúng.
    • có thể xác định các kênh kênh khác nhau cho một SocketChannel không?
    • phương pháp tiếp cận khác?

Cảm ơn sự giúp đỡ của bạn!

KJ

Đây là cách các máy chủ được tạo ra:

public void run() throws Exception { 

    EventLoopGroup bossGroup = new NioEventLoopGroup(1); 
    EventLoopGroup workerGroup = new NioEventLoopGroup(); 
    try { 
     ServerBootstrap b = new ServerBootstrap(); 
     b.group(bossGroup, workerGroup) 
     .channel(NioServerSocketChannel.class) 
     .handler(new LoggingHandler(LogLevel.INFO)) 
     .childHandler(new ChannelInitializer<SocketChannel>() { 
      @Override 
      public void initChannel(SocketChannel ch) throws Exception { 
       ChannelPipeline p = ch.pipeline(); 
       p.addLast(
        new ObjectEncoder(), 
        new ObjectDecoder(ClassResolvers.cacheDisabled(null)), 
        new ConfigServerHandler(), 
        new FeedbackServerHandler()); 
      } 
     }); 
     b.bind(mPort).sync().channel().closeFuture().sync(); 
    } finally { 
     bossGroup.shutdownGracefully(); 
     workerGroup.shutdownGracefully(); 
    } 
} 

Một trong những lớp Handler (các FeedbackServerHandler không giống hệt nhau nhưng phân tích thành Integer):

public class ConfigServerHandler extends ChannelInboundHandlerAdapter { 

    @Override 
    public void channelRead(ChannelHandlerContext ctx, Object msg) { 
     System.out.println("ConfigServerHandler::channelRead, " +(String)msg); 
     ctx.write(msg); 
    } 

    @Override 
    public void channelReadComplete(ChannelHandlerContext ctx) { 
     ctx.flush(); 
    } 

    @Override 
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 
     cause.printStackTrace(); 
     ctx.close(); 
    } 
} 

Các mặt khách hàng trông khá giống nhau:

public Client(String host, int port) throws InterruptedException { 

    EventLoopGroup workerGroup = new NioEventLoopGroup(); 
    try { 
     Bootstrap b = new Bootstrap(); 
     b.group(workerGroup) 
     .channel(NioSocketChannel.class) 
     .handler(new ChannelInitializer<SocketChannel>() { 
      @Override 
      public void initChannel(SocketChannel ch) throws Exception { 
       ChannelPipeline p = ch.pipeline(); 
        p.addLast(
         new ObjectEncoder(), 
         new ObjectDecoder(ClassResolvers.cacheDisabled(null)), 
         new ConfigClientHandler(), 
         new FeedbackClientHandler()); 
      } 
     }); 
     b.connect(host, port).sync().channel().closeFuture().sync(); 
    } finally { 
     workerGroup.shutdownGracefully(); 
    } 
} 

Và đây là một trong những bộ xử lý phía khách hàng (một trong những khác gửi một thông báo Integer và phân tích thành Integer trong phương pháp 'channelRead'):

public class ConfigClientHandler extends ChannelInboundHandlerAdapter { 

    private final String firstMessage = "blubber"; 

    @Override 
    public void channelActive(ChannelHandlerContext ctx) { 
     System.out.println("ConfigClientHandler::channelActive"); 
     ctx.writeAndFlush(firstMessage); 
    } 

    @Override 
    public void channelRead(ChannelHandlerContext ctx, Object msg) { 
     System.out.println("ConfigClientHandler::channelRead, " +(String)msg); 
     ctx.write(msg); 
    } 

    @Override 
    public void channelReadComplete(ChannelHandlerContext ctx) { 
     ctx.flush(); 
    } 

}

Trả lời

5

Bạn đang sử dụng ChannelInboundHandlerAdapter, đó là tốt, cho xử lý "trung bình" của bạn ConfigXxxxxHandler.

Nhưng bạn sử dụng phương pháp channelRead và sau đó sử dụng bên trong ctx.write(msg). ctx.write(msg) sẽ ghi lại thư đó trở lại máy chủ khác thông qua trình xử lý trước đó trước tiên (ObjectDecoder), không phải cho trình xử lý tiếp theo (FeedbackClientHandler trong trường hợp của bạn).

Bạn nên sử dụng sau đây nếu bạn muốn gửi thông điệp tới xử lý tiếp theo:

@Override 
public void channelRead(ChannelHandlerContext ctx, Object msg) { 
    System.out.println("ConfigClientHandler::channelRead, " +(String)msg); 
    ctx.fireChannelRead(msg); 
} 

Và tất nhiên không ctx.flush() trong (vì không có nhiều viết có). Nhưng trong lần cuối cùng của bạn FeedbackClientHandler, tất nhiên, hãy sử dụng phương pháp tuôn ra với ctx.write(yourNewMessage) hoặc sử dụng ctx.writeAndFlush(yourNewMessage).

Vì vậy, để tiếp tục:

  • ctx.write sẽ gửi thông điệp tới các dây, như vậy để xử lý trước xuống kênh sau đó vào mạng, vì vậy Outbound cách
  • ctx.fireChannelRead sẽ gửi tin nhắn để xử lý tiếp theo sau (cách ngược lại), vì vậy Inbound cách

Xem http://netty.io/wiki/new-and-noteworthy-in-4.0.html#wiki-h4-16 để biết chi tiết .

Bạn có lẽ cũng nên đảo ngược Bộ mã hóa/Bộ giải mã, vì nói chung, tốt nhất nên có bộ giải mã đầu tiên, sau đó là bộ mã hóa trong đường ống.

  p.addLast(
         new ObjectDecoder(ClassResolvers.cacheDisabled(null)), 
         new ObjectEncoder(), 
         new ConfigClientHandler(), 
         new FeedbackClientHandler()); 
Các vấn đề liên quan