// Create the server socket channel
ServerSocketChannel server = ServerSocketChannel.open();
// nonblocking I/O
server.configureBlocking(false);
// host-port 8000
server.socket().bind(new java.net.InetSocketAddress(host,8000));
// Create the selector
Selector selector = Selector.open();
// Recording server to selector (type OP_ACCEPT)
server.register(selector,SelectionKey.OP_ACCEPT);
while (true) {
selector.select(); // blocking operation
Iterator it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey selKey = (SelectionKey) it.next();
// THE MOST INTRIGUING PART HERE!!!
if (selKey.isAcceptable()) {
ServerSocketChannel ssChannel = (ServerSocketChannel) selKey.channel();
SocketChannel sc = ssChannel.accept();
}
it.remove();
}
}
我这里有几个问题:
- selKey.channel() return a ServerSocketChannel is it exactly the same channel we created in the beggining with ServerSocketChannel.open()? If not, then what is it?
- More important question: in most other tutorials selKey.channel(); step is skipped and they simply use SocketChannel client = server.accept(); For example here: http://www.onjava.com/pub/a/onjava/2002/09/04/nio.html?page=2 and here: http://www.developer.com/java/article.php/10922_3837316_2/Non-Blocking-IO-Made-Possible-in-Java.htm So, how does server.accept() knows about current key we process?
In http://www.developer.com/java/article.php/10922_3837316_2/Non-Blocking-IO-Made-Possible-in-Java.htm they even suggest to accept channel in new thread. I guess it is possible that the following situation may occur.
key1 someClient1 acceptable key2 someClient2 not acceptable key3 someClient3 acceptable startThread1 startThread3 scheduler decides to give time to thread3 instead of thread1 thread3 -> socket.accept() <- actually accepts client1 thread1 -> socket.accept() <- actually accepts client3
Can I simply do the following:
int availableClients = 0; while (it.hasNext()) { SelectionKey selKey = (SelectionKey) it.next(); if (selKey.isAcceptable()) { ++availableClients; } it.remove(); } for (int i = 0; i < availableClients; ++i) { SocketChannel sc = server.accept(); doSomething(sc); }
ServerSocketChannel
键,并接受一个新创建的SocketChannel
,该通道连接到新客户端。其相关性在于当OP__ACCEPT触发时,accept()
不会返回null
。 - user207421SelectionKey
。通道有两种类型:ServerSocketChannel
和SocketChannel
。我认为你在某个地方存在严重的误解,但我无法找出问题所在。 - user207421