java - Netty 4 调用被阻止,简单的 Telnet 服务器

标签 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,有什么方法可以使其完全异步,以便在套接字上可用时立即接收三个hello。

最佳答案

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

如果其他操作是其他类型的连接,您也应该将其用作异步连接。只有每个部分都正确执行此操作,您才能实现异步。

关于java - Netty 4 调用被阻止,简单的 Telnet 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35744076/

相关文章:

java - 如何使用Java中的objectinputstream多次从服务器读取文件

java - 如何使用 Java 套接字读取远程服务器的响应

当我对我的 HTTP 服务器进行压力测试时,Windows 暂时关闭了我的 TCP 堆栈

javascript - Websockets 消息完整性

java - 如何逐行打印字符串对象

java - 如何将 Java 源代码漂亮地打印为 PDF?

java - 通过改造处理 gzip 响应

java - 从字符串中提取两个具有千个分隔符的数字

javascript - 如何同步执行socket.io端点

Java Hibernate 与数据库的连接几分钟后超时