Java NIO study notes (c) Selector Selector

Section using the analog channel channel client sends a message to the server . Code is based on synchronous blocking IO. This efficiency is low, and a process server can only handle a client connection. This section learning Selector Selector. Allows a server to handle multiple client connections, the performance has greatly improved.

A, Selector Selector Introduction

Selector in NIO is another important realization. Selector is a Java implementation of a multiplexed IO model of one of the five models. You can monitor multiple channels simultaneously non-blocking sockets.

Here Insert Picture Description

1. Select the key SelectKey

Select key includes four events, by selecting the button, you can select an event we find to be selected are:

public static final int OP_READ = 1 << 0;

public static final int OP_WRITE = 1 << 2;

public static final int OP_CONNECT = 1 << 3;

public static final int OP_ACCEPT = 1 << 4;

Between events may be combined by OR operation.
You can determine whether the event ready by the following method. We polled by Selector, the event we need to see whether the ready.

selectionKey.isAcceptable();

selectionKey.isConnectable();

selectionKey.isReadable();

selectionKey.isWritable();

2, channel registration

We are interested in the issue to the attention Selector, the time until an event occurs, Seletor can return to ready the event and do follow-up things.

       //  切换成非阻塞模式
        serverSocketChannel.configureBlocking(false);

        // 将通道注册到选择器上
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

3, the selection process

Selector selection method comprising 3 different functions

  • int select () This is a method of blocking at least one channel in the ready state when the return
  • int select (long timeout) is also a blocking method, but this method can set the timeout that is not consistent thread is blocked
  • int selectNow () non-blocking method, immediately after the call returns

Second, agents, and demonstrate examples

Relatively fixed code server, reference to the following comments may be well understood. It should be noted that after the end of each inner loop, this poll will need to remove all the selected key off to start a new poll.

/**
 * @author Time
 * @created 2019/8/28
 */
public class TcpSelectServer {
    public static void main(String[] args) throws IOException {
        // 1. 获取通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 2. 切换成非阻塞模式
        serverSocketChannel.configureBlocking(false);
        // 3.绑定连接
        serverSocketChannel.bind(new InetSocketAddress(8080));
        // 4.获取选择器
        Selector selector = Selector.open();
        // 5.将通道注册到选择器上
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        // 6. 轮询式获取选择器上已经准备就绪的通道
        while(selector.select() > 0 ){
            // 7.获取当前选择器中所有的注册事件
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()){
                // 获取准备就绪的事件
                SelectionKey sk = iterator.next();
                // 判断具体是什么事件
                if(sk.isAcceptable()){
                    // 获取客户端非阻塞
                    SocketChannel s = serverSocketChannel.accept();
                    // 切换非阻塞模式
                    s.configureBlocking(false);
                    // 将该通道注册到选择器上
                    s.register(selector,SelectionKey.OP_READ);
                }else  if (sk.isReadable()){
                    // 获取当前选择器上读就绪通道
                    SocketChannel socketChannel = (SocketChannel) sk.channel();
                    // 读取数据
                    ByteBuffer buffer = ByteBuffer.allocate(128);
                    int len = 0;
                    while((len = socketChannel.read(buffer)) > 0){
                        buffer.flip();
                        System.out.println(new String(buffer.array(),0,len));
                        buffer.clear();
                    }
                }
                // 取消选择键
                iterator.remove();
            }
        }
    }
}

Client code

/**
 * @author Time
 * @created 2019/8/28
 * 非阻塞式客户端
 */
public class TcpNonBlockingClient01 {
    public static void main(String[] args) throws IOException {
        // 1. 获取通道
        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("localhost",8080));
        // 2.切换成非阻塞模式
        socketChannel.configureBlocking(false);
        // 3.分配指定大小的缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(128);
        // 4.发送数据给服务器
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNext()){
            String str = scanner.nextLine();
            buffer.put((new Date().toString() + "\n" + str).getBytes());
            buffer.flip();
            socketChannel.write(buffer);
            buffer.clear();
        }

        // 5. 关闭通道
        socketChannel.close();
    }
}

The demo: You can now find a process server can handle multiple connections
Here Insert Picture Description

Published 66 original articles · won praise 26 · views 10000 +

Guess you like

Origin blog.csdn.net/Time__Lc/article/details/100121502