【问题标题】:How do I make this non-blocking server multi-threaded?如何使这个非阻塞服务器多线程?
【发布时间】:2011-06-15 17:01:15
【问题描述】:

我正在尝试允许多个连接到一个小型 Java 服务器类型的应用程序。它按原样工作,但如果一个连接打开然后挂起,所有后续连接都将挂起。我不确定如何处理每个连接,在他们自己的线程中最多有大约 20 个并发连接,同时跟踪哪个线程属于哪个客户端等。我到目前为止的代码是:

private void init() {
    try {
        // Create the server socket channel
        ServerSocketChannel server = ServerSocketChannel.open();
        // nonblocking I/O
        server.configureBlocking(false);
        // host-port 
        server.socket().bind(new InetSocketAddress(host, port));
        System.out.println("Server connected on " + host + ":" + port);
        // Create the selector
        Selector selector = Selector.open();
        // Recording server to selector (type OP_ACCEPT)
        server.register(selector, SelectionKey.OP_ACCEPT);
        // Infinite server loop
        for (;;) {
            // Waiting for events
            selector.select();
            // Get keys
            Set keys = selector.selectedKeys();
            Iterator i = keys.iterator();
            // For each keys...
            while (i.hasNext()) {
                SelectionKey key = (SelectionKey) i.next();
                // Remove the current key
                i.remove();
                // if isAccetable = true
                // then a client required a connection
                if (key.isAcceptable()) {
                    // get client socket channel
                    SocketChannel client = server.accept();
                    // Non Blocking I/O
                    client.configureBlocking(false);
                    // recording to the selector (reading)
                    client.register(selector, SelectionKey.OP_READ);
                    continue;
                }
                // then the server is ready to read
                if (key.isReadable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    // Read byte coming from the client
                    int BUFFER_SIZE = 32;
                    ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
                    try {
                        client.read(buffer);
                    } catch (Exception e) {
                        // client is no longer active
                        e.printStackTrace();
                        continue;
                    }
                    buffer.flip();
                    Charset charset = Charset.forName("ISO-8859-1");
                    CharsetDecoder decoder = charset.newDecoder();
                    CharBuffer charBuffer = decoder.decode(buffer);
                    Handler dataHandler = new Handler();
                    client.write(ByteBuffer.wrap(dataHandler.processInput(charBuffer.toString()).getBytes()));
                    client.socket().close();
                    continue;
                }
            }
        }
    } catch (IOException ex) {
        Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
    }
}

【问题讨论】:

  • 我只使用阻塞 NIO 并且每个客户端有一个线程,它会简单得多,并且可以扩展到 10K 连接。它还可以更高效。

标签: java multithreading sockets threadpool


【解决方案1】:

每当我需要编写套接字服务器时,我都会避免使用低级 JVM 类,因为需要处理所有细节。

相反,我使用Apache Mina。这是一个用于编写高性能非阻塞多线程套接字服务器的 Java 库。

使用 Mina 的另一个好处是它强制执行 clean architecture(IoFilters,协议解码器),这使您的代码更加模块化并更易于维护。

【讨论】:

  • 听起来很有希望......我会看看然后回来。我真的需要熟悉更多的 Apache 项目......
【解决方案2】:

除非你真的想编写 NIO 服务器作为学习练习,否则我建议使用 Netty。就像 Peter 提到的 Mina 一样,它也是一个用于编写高性能服务器的库。

我最近从使用自己的 NIO 代码转移到了这个库,它让我的代码变得更加简洁。

【讨论】:

  • 我完全支持任何可以让生活更简单而无需太多开销的东西,所以我也会结帐 netty
【解决方案3】:

我的解决方案是创建 ThreadPool 的 Netty 和 Executor。 您只需添加处理程序做 Netty 的管道,它调用 executor witch ChannelBuffer 作为参数。 比每个客户端请求都将由单独的线程处理。

examples

【讨论】:

  • 最后使用了netty,没有外部部门。并且似乎非常适合,进入 API 的学习曲线有多陡?
  • 您将能够在一分钟内制作基本服务器,但最好深入了解网络资源以了解其工作原理。这对我来说是一个很好的教训 :) 我建议阅读有关内置处理程序 - 解码器/编码器的信息。我构建我的服务器只是将一些类添加到管道中。 HTTP、SSL,随便你:)
  • 在这里你可以很好地比较 Netty 和 Mina:stackoverflow.com/questions/1637752/netty-vs-apache-mina
猜你喜欢
  • 2019-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-25
  • 1970-01-01
  • 1970-01-01
  • 2015-11-25
  • 2021-09-18
相关资源
最近更新 更多