【问题标题】:How Can I create different selectors for accepting new connection in java NIOjava - 如何在java NIO中创建不同的选择器以接受新连接
【发布时间】:2010-10-28 13:46:09
【问题描述】:

我想用java NIO写java tcp socket编程。它工作正常。但我使用相同的选择器来接受客户端的读取和写入。

如何创建不同的选择器来接受 java NIO 中的新连接、读取和写入。 有没有在线帮助。

实际上,当我忙于阅读或编写时,我的选择器会使用更多的迭代器。因此,如果连接的客户端数量更多,那么接受新连接的性能就会变慢。 但我不希望接受客户变慢

// 创建一个选择器并注册两个套接字通道 选择器选择器 = null; 尝试 { // 创建选择器 选择器 = Selector.open();

    // Create two non-blocking sockets. This method is implemented in
    // e173 Creating a Non-Blocking Socket.
    SocketChannel sChannel1 = createSocketChannel("hostname.com", 80);
    SocketChannel sChannel2 = createSocketChannel("hostname.com", 80);

    // Register the channel with selector, listening for all events
    sChannel1.register(selector, sChannel1.validOps());
    sChannel2.register(selector, sChannel1.validOps());
} catch (IOException e) {
}

// Wait for events
while (true) {
    try {
        // Wait for an event
        selector.select();
    } catch (IOException e) {
        // Handle error with selector
        break;
    }

    // Get list of selection keys with pending events
    Iterator it = selector.selectedKeys().iterator();

    // Process each key at a time
    while (it.hasNext()) {
        // Get the selection key
        SelectionKey selKey = (SelectionKey)it.next();

        // Remove it from the list to indicate that it is being processed
        it.remove();

        try {
            processSelectionKey(selKey);
        } catch (IOException e) {
            // Handle error with channel and unregister
            selKey.cancel();
        }
    }
}

public void processSelectionKey(SelectionKey selKey) throws IOException {
    // Since the ready operations are cumulative,
    // need to check readiness for each operation
    if (selKey.isValid() && selKey.isConnectable()) {
        // Get channel with connection request
        SocketChannel sChannel = (SocketChannel)selKey.channel();

        boolean success = sChannel.finishConnect();
        if (!success) {
            // An error occurred; handle it

            // Unregister the channel with this selector
            selKey.cancel();
        }
    }
    if (selKey.isValid() && selKey.isReadable()) {
        // Get channel with bytes to read
        SocketChannel sChannel = (SocketChannel)selKey.channel();

        // See e174 Reading from a SocketChannel
    }
    if (selKey.isValid() && selKey.isWritable()) {
        // Get channel that's ready for more bytes
        SocketChannel sChannel = (SocketChannel)selKey.channel();
        }
}

谢谢 迪帕克

【问题讨论】:

  • 客户端被 TCP 栈预先接受。这就是积压队列的用途。其性能不受迭代器性能的影响。你的问题似乎毫无意义。你可以很容易地增加积压,这就是你所需要的。

标签: java nio


【解决方案1】:

每个选择器都需要自己的线程。

如果你想要多个选择器,为什么不使用阻塞 NIO,那会很多简单。非阻塞 IO 仅在您想要连接以共享线程时才有意义。

【讨论】:

  • 我没有看到任何暗示不能在同一个线程上使用两个选择器的信息。这对我来说似乎很好用(尽管出于我能想到的任何原因,两个也不是必需的)。
  • 您可以在一个线程中使用任意数量的选择器。但是,我不明白这一点,即单个选择器不会为您提供什么?
  • 听起来我们意见一致。只是“需要自己的线程”的措辞让我感到困惑。可以让一个选择器专门处理接受操作,因此您可以优先处理这些操作而不是读/写操作。我认为这就是他所要求的,尽管这没有任何意义,并且如果没有额外的工作,实际上不会以他期望的方式提高性能。
  • 有一些在不同阶段使用多个选择器的有效模式。例如,一个选择器接受与另一个选择器的连接以进行主动读/写。有时,这可以更容易处理 SelectionKeys 的“怪癖”,因为工作线程还没有开始清除操作,或者问题更改非 select() 调用线程中的兴趣操作。灰熊在这方面做得很好。
  • 操作应该在选择线程中被清除,而不是工作线程。这只是自找麻烦。
【解决方案2】:

online help 很多。

如果您想创建一个新的选择器,请继续创建另一个(与您复制的示例代码中的操作相同)。如果需要,您可以使用它为连接操作注册通道(文档涵盖了这一点,但操作是 OP_ACCEPT)。您可能需要一个线程池来处理客户端处理的工作 - 这样您的主线程可以将工作项排队并立即重新接受侦听套接字上的新连接。

【讨论】:

  • 那么为什么不粘贴您实际使用的任何代码,而不是示例客户端代码呢?如果您接受连接,则必须在某处使用 ServerSocketChannel。
猜你喜欢
  • 1970-01-01
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
  • 2013-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多