NIO selector Selector

NIO selector Selector

In the last of further in-depth in JAVA NIO we learned how to use Buffer, but in Java NIO in the IO and we learned a little Channelof the concept, we know that Channeljust like mined the tracks, Bufferjust like mine car on the tracks for data operations are for real Bufferoperations. And there is a very important concept in the NIO Selector, it is like mined in the same scheduling system.

Why should Selector

To understand why there must Selector? This question, we first have to know that there are five I / O model on UNIX systems: synchronous blocking I / O, non-blocking synchronous I / O, I / O multiplexing, signal driven I / O and asynchronous I / O . The several I / O model is what does that mean, what about metaphor.

  • Blocking I / O model: a man fishing when the fish did not bite, and so on has been sitting on the shore.
  • Non-blocking I / O model: while fishing play phone, and then see if there will be every fish hook, any quickly pull rod.
  • I / O multiplexing model: put a bunch of fishing rod, on the shore have been guarding the pile of fishing rod, not a fish bites on the play phone.
  • Signal-driven I / O model: tied a cowbell on the fishing rod, when the bell rang, I know the fish hook, you can then concentrate on playing mobile phone.
  • Asynchronous I / O model: hire someone to give me a fish, give me to the residence after the catch, I Why Why.

Blocking and non-blocking refers to the application when initiating I / O operation is returned immediately or wait. Asynchronous and synchronized means that the application core communications, data from the copy of the application space to the kernel space, is initiated or triggered by the core by the application.

The so-called I / O is the data copy process between the computer memory and an external device , we know that the CPU speed is much higher than the external memory access apparatus, so the CPU is usually the first read data to the external memory device, and and then processed. Then there is a scene at this time, that when your user program sends a read command to the external device through the CPU, data from the external memory device to take some time, then the CPU is the rest of it at this time? Or to others? Or constantly asked to do? Reached? Reached……? This is the problem I / O model to be solved.

Our NIO analog I / O model is the I / O multiplexing model. By blocking only Selectorthis one thread, by Selectorconstantly query Channelin the state, so as to achieve a thread control Selector, and a Selectorplurality of control Channelpurposes. It is represented by this map.

Selector Use

From the chart above we can probably guess Selectorhow to use

Creating Selector

By calling Selector.open()to create a Selector method.

Selector selector = Selector.open();
复制代码

Create a Channel needed

We know that in NIO Channel is divided into four types

  • FileChannel: File channel
  • DatagramChannel: Reading data network via UDP
  • SocketChannel: Reading data network by TCP
  • ServerSocketChannel: You can listen for incoming connections, create a will for each incoming connectionSocketChannel

And in that there is not a four channels Selectorwith the use, as can be seen from the figure, we Selectorare constantly registered in the polling Selectorstate of each channel can not be blocked in one of the channels, each channel must i.e. is unblocked, but FileChannelthe channel is blocked and can not be changed, it FileChannelcan not be Selectorused in conjunction.

ServerSocketChannel socketChannel = ServerSocketChannel.open();
socketChannel.socket().bind(new InetSocketAddress(8080));
//设置为非阻塞模式
socketChannel.configureBlocking(false);

复制代码

Will create good Channel Selector registered with the

For ease of Selectoradministration Channel, we will Channelregister to Selectorthe.

//将Channel注册到Selector上
SelectionKey selectionKey = socketChannel.register(selector,SelectionKey.OP_READ);

复制代码

We can see that the first parameter is our own Selector, and the second parameter is to select the type of event to listen, a total of four

  • SelectionKey.OP_CONNECT: Connecting to continue the event, indicates that the server listens to client connection, the server can accept the connection
  • SelectionKey.OP_ACCEPT: Connecting ready event, the server receives a connection request from a client trigger
  • SelectionKey.OP_READ: Ready for reading event indicating the channel of the data has been read, a read operation may be performed
  • SelectionKey.OP_WRITE: Write-ready event, said it had to write the data to the channel

ServerSocketChannelThe events are effective OP_ACCEPT, SocketChanneleffective events OP_CONNECT, OP_READ,OP_WRITE

Loop through each Channel Selector

In the last step we have required Channelregistration to Selector, then we can now call the Selector.select()method has been traversed to get ready Channel.


Set<SelectionKey> selectedKeys = selector.selectedKeys();

Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

while(keyIterator.hasNext()) {
    
    SelectionKey key = keyIterator.next();

    if(key.isAcceptable()) {
        // a connection was accepted by a ServerSocketChannel.

    } else if (key.isConnectable()) {
        // a connection was established with a remote server.

    } else if (key.isReadable()) {
        // a channel is ready for reading

    } else if (key.isWritable()) {
        // a channel is ready for writing
    }

    keyIterator.remove();
}

复制代码

Note that at this time we traversed after completion, after the completion of the corresponding operation should call the keyIterator.remove();method to remove it out, because the select()method has only been all ready Channelset of values key, if not removed, then the next traversal will still remain call the corresponding event.

Complete Example

Make a simple server monitor program. This machine monitor 8080, the print data sent from.


public class TestNIO {

    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();
        ServerSocketChannel socketChannel = ServerSocketChannel.open();
        socketChannel.socket().bind(new InetSocketAddress(8080));
        //设置为非阻塞模式
        socketChannel.configureBlocking(false);
        //将Channel注册到Selector上
        socketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (true){
            int readyChannel = selector.select();
            if (readyChannel == 0){
                continue;
            }
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
            while (keyIterator.hasNext()){
                SelectionKey key = keyIterator.next();
                keyIterator.remove();
                if (key.isAcceptable()){
                    System.out.println("isAcceptable");
                    SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept();
                    clientChannel.configureBlocking(false);
                    clientChannel.register(key.selector(),SelectionKey.OP_READ);
                }
                else if (key.isConnectable()){
                    System.out.println("isConnectable");
                }
                else if (key.isReadable()){
                    SocketChannel clientChannel = (SocketChannel) key.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    clientChannel.read(byteBuffer);
                    System.out.println(new String(byteBuffer.array()));
                }else if (key.isWritable()){
                    System.out.println("isWritable");
                }
            }
        }
    }
}

复制代码

At this time, by the console command telnet localhost 8080to connect to the server.

Reference article

Guess you like

Origin juejin.im/post/5cff6169e51d4556f76e8078