Netty 4呼叫被阻止,简单的Telnet服务器

时间:2016-03-02 10:09:15

标签: java sockets connection netty

我正在尝试使用Netty Telnet服务器来使用netty api来检查是否可以观察到真正的异步行为。

以下是正在使用的三个类

TelnetServer.java

public class TelnetServer {

    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
          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 TelnetServerInitializer());


              b.bind(8989).sync().channel().closeFuture().sync();
          } finally {
              bossGroup.shutdownGracefully();
              workerGroup.shutdownGracefully();
          }
    }

}

TelnetServerInitializer.java

public class TelnetServerInitializer extends ChannelInitializer<SocketChannel> {

    private static final StringDecoder DECODER = new StringDecoder();
    private static final StringEncoder ENCODER = new StringEncoder();

    private static final TelnetServerHandler SERVER_HANDLER = new TelnetServerHandler();


    final EventExecutorGroup executorGroup = new DefaultEventExecutorGroup(2);

    public TelnetServerInitializer() {

    }

    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();


        // Add the text line codec combination first,
        pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        // the encoder and decoder are static as these are sharable
        pipeline.addLast(DECODER);
        pipeline.addLast(ENCODER);

        // and then business logic.
        pipeline.addLast(executorGroup,"handler",SERVER_HANDLER);
    }
}

TelnetServerHandler.java

/**
 * Handles a server-side channel.
 */
@Sharable
public class TelnetServerHandler extends SimpleChannelInboundHandler<String> {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // Send greeting for a new connection.
        ctx.write("Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
        ctx.write("It is " + new Date() + " now.\r\n");
        ctx.flush();
        ctx.channel().config().setAutoRead(true);
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, String request) throws Exception {
        // Generate and write a response.

        System.out.println("request = "+ request);

        String response;
        boolean close = false;
        if (request.isEmpty()) {
            response = "Please type something.\r\n";
        } else if ("bye".equals(request.toLowerCase())) {
            response = "Have a good day!\r\n";
            close = true;
        } else {
            response = "Did you say '" + request + "'?\r\n";
        }

        // We do not need to write a ChannelBuffer here.
        // We know the encoder inserted at TelnetPipelineFactory will do the conversion.
        ChannelFuture future = ctx.write(response);

        Thread.sleep(10000);
        // Close the connection after sending 'Have a good day!'
        // if the client has sent 'bye'.
        if (close) {
            future.addListener(ChannelFutureListener.CLOSE);
        }
    }

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

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

现在我通过telnet客户端连接并发送命令hello hello hello三次

在第一次对channelRead的响应完成之前,请求没有到达channelRead是否有任何办法可以使它完全异步,以便在socket上可用时立即收到三个hello。

1 个答案:

答案 0 :(得分:1)

对于每个处理程序的每个传入读取,Netty最多使用1个线程,这意味着只有在前一个调用完成后才会调度对channelRead的下一次调用。这对于大多数处理程序的正确工作是必需的,包括以正确的顺序发回消息。如果计算量非常复杂,另一种解决方案是使用自定义线程池来处理消息。

如果其他操作是另一种连接,则应将其用作异步连接。如果每个部分都正确执行此操作,则只能获得异步。