为什么NIO选择器始终从端口列表中侦听上一个端口?

时间:2015-07-24 10:07:15

标签: java multithreading nio

以下是我的审核代码。 1.我正在使用在3个端口上发送数据的模拟器。 但我的代码从端口列表的最后一个端口写入数据。例如端口2002,3002,4002和代码只监听4002。 NIO选择器必须转向所有端口。

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
import java.util.Set;
public class ServerSockets {

     public static void main(String[] args) throws IOException 
     {
         int ports[] = new int[] {2002,3002,4002};
         Selector selector =null;

        // loop through each port in our list and bind it to a ServerSocketChannel
        for (int port : ports) {
            ServerSocketChannel serverChannel = ServerSocketChannel.open();
            serverChannel.configureBlocking(false);
            serverChannel.socket().bind(new InetSocketAddress(port));
            selector = Selector.open();
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        }


 //check for all port whom ready to send data
 while (true) {

     // our canned response for now
     ByteBuffer resp = ByteBuffer.wrap(new String("got it\n").getBytes());
     try {
         // loop over all the sockets that are ready for some activity
         while (selector.select() > 0) {
             Set keys = selector.selectedKeys();
             Iterator i = keys.iterator();
             while (i.hasNext()) {
                 SelectionKey key = (SelectionKey)i.next();
                 if (key.isAcceptable()) {
                     // this means that a new client has hit the port our main
                     // socket is listening on, so we need to accept the  connection
                     // and add the new client socket to our select pool for reading
                     // a command later
                     System.out.println("Accepting connection!");
                     // this will be the ServerSocketChannel we initially registered
                     // with the selector in main()
                     ServerSocketChannel sch = (ServerSocketChannel)key.channel();
                     SocketChannel ch = sch.accept();
                     ch.configureBlocking(false);
                     ch.register(selector, SelectionKey.OP_READ);
                 } else if (key.isReadable()) {
                     // one of our client sockets has received a command and
                     // we're now ready to read it in
                     System.out.println("Accepting command!");                            
                     SocketChannel ch = (SocketChannel)key.channel();
                     ByteBuffer buf = ByteBuffer.allocate(200);
                     ch.read(buf);
                     buf.flip();
                     Charset charset = Charset.forName("UTF-8");
                     CharsetDecoder decoder = charset.newDecoder();
                     CharBuffer cbuf = decoder.decode(buf);
                     System.out.print(cbuf.toString());
                     // re-register this socket with the selector, this time
                     // for writing since we'll want to write something to it
                     // on the next go-around
                   // ch.register(selector, SelectionKey.OP_READ);
                 } else if (key.isWritable()) {
                     // we are ready to send a response to one of the client sockets
                     // we had read a command from previously
                     System.out.println("Sending response!");
                     SocketChannel ch = (SocketChannel)key.channel();
                     ch.write(resp);
                     resp.rewind();
                     // we may get another command from this guy, so prepare
                     // to read again. We could also close the channel, but
                     // that sort of defeats the whole purpose of doing async
                     ch.register(selector, SelectionKey.OP_READ);
                 }
                 i.remove();
             }
         }
     } catch (IOException e) {
         System.out.println("Error in poll loop");
         System.out.println(e.getMessage());
         System.exit(1);
     }
 }

} }

1 个答案:

答案 0 :(得分:1)

您多次创建Selector,因此您最终只使用最后创建的一个,只创建了您创建的最后一个ServerSocketChannel。将其移出循环,然后再开始。