NIO - Selector in Java network programming

Keywords: Java network Programming socket

Preface

I have a general understanding of NIO operation and three components
Java network programming (4) NIO understanding and three components of NIO
And learn in detail: Buffer and Channel
Java network programming (5) NIO - Buffer details
Java network programming (6) NIO - Channel details

Next, complete the learning of Selector

Catalog

  1. Selector function
  2. Selector class inheritance relationship
  3. common method
  4. SelectionKey
  5. A case of chat system
  6. summary

Selector function

NIO programming structure:


Selectors enable a thread to handle multiple channels. Selectors poll the channels registered on them. Selectors can only manage non blocking channels. File channels (filechannels, etc.) are blocked and cannot be managed

So Selector is the Selector of network communication channel. The most common operation is to operate ServerSocketChannel and SocketChannel

Selector class inheritance relationship


Selector is an abstract class with many subclasses, among which the implementation class is WindowsSelectorImpl

common method

The Selector itself has these methods:

  1. instantiation
    Because the Selector is an abstract class, that is, it cannot be instantiated with new. To obtain a Selector object through the open() method
Selector selector = Selector.open();
  1. select()
    The select() method monitors all channels registered on the selector. When there is IO operation available, the SelectionKey corresponding to the channel is added to the collection and returned (the SelectionKey is an important object)
  2. select(long timeout)
    Because the select method is blocked, that is, you must wait until an event occurs in a channel, and you can set the TimeOut to unblock
  3. selectNow()
    Non blocking select method
  4. selectedKeys()
    Get the SelectionKey of the existing event
  5. keys()
    The SelectionKey of all registered channels is saved
  6. isOpen()
    Determine whether the selector is on
  7. wakeup()
    Wake up selector
    selector.select() is blocked. Generally, select() will wake up from the block only when the channel registered on the selector has event ready. When the channel on the selector has no ready event, if you want to wake up the blocked thread on the select() operation to handle some other work, you can use the wakeup method

SelectionKey


SelectionKey is an abstract class, and the implementation class is SelectionKeyImpl class

Selectionkey indicates the identity of the SelectableChannel registered in the Selector. When each Channel registers with the Selector, a selectionkey will be created

SelectableChannel is the parent class of various network channels, which can be transformed to the Channel we want

Use

SelectionKey object. This object contains some properties:

  • interest set: the selected set of interested events
  • Ready set: the set of operations for which the channel is ready
  • Channel: SelectionKey can get the marked channel object
  • Selector: SelectionKey can get the selector object used
  • Additional object (optional): you can attach an object or more information to the SelectionKey, so that you can easily identify a given channel, such as attaching a Buffer

  1. Operation set

When a channel is registered with a selector, you can select the events to listen to
For example, serverSocketChannel needs to listen for request connection events

//Register, server listens for request connection events
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

Selectionkey.op'accept is an operation set

SelectionKey has four operation sets, which are bitwise operation values:

OP? Read value is 1
Op'write value is 4
OP? Connect is 8
The op? Accept value is 16

interesOps(): get the inter collection of this SelectionKey
interestOps(int ops): set the interest of this SelectionKey to the specified value (previously set at registration time)

  1. Channel()
    Returns the channel associated with this selection key. Even if this key has been cancelled, it will still return
    In reading and writing operations, this method is generally used to obtain the Channel through SelectionKey
  2. Selector()
    Returns the Selector associated with this selection key
  3. Attached objects: attachment()
    You can choose to set a buffer when registering
socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));

This reduces the overhead of the buffer, which is then obtained by the attachment method

ByteBuffer byteBuffer = (ByteBuffer) key.attachment();

Of course, it can be set on the SelectionKey
attach(Object ob): add the given object as an attachment to this key

  1. ready set: judge events
    isAcceptable(): judge whether it is a connection event (used by server channel)
    isValid(): judge whether the key is valid
    isReadable(): check whether the key is a "read" event

A case of chat system

The server

package com.company.Selector.Selector1;



import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

public class NIOServer {
    public static void main(String[] args) throws Exception {
        //Open ServerSocketChannel to wait for connection
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //Set non blocking
        serverSocketChannel.configureBlocking(false);
        //Binding port number 6666
        serverSocketChannel.socket().bind(new InetSocketAddress(6666));
        //Open selector
        Selector selector = Selector.open();
        //Register and listen for connection events
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true){
            //Loop monitoring
            //select is the blocking method
/*            if ( selector.select(5000)==0){
                System.out.println("No client connection ');
                continue;
            }*/
            selector.select();
            //Get the SelectionKey of the existing event
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            //Iterative Set set
            Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
            while (keyIterator.hasNext()){

                SelectionKey key = keyIterator.next();
                if (key.isAcceptable()){
                    System.out.println("Get client connection");
                    //accept to get SocketChannel
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    //Set non blocking
                    socketChannel.configureBlocking(false);
                    //Register, socketChannel listens for read events
                    //Associate a bytebuffer
                    //socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }
                if (key.isReadable()){
                    //The channel method of SelectionKey to get SocketChannel
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    //Get buffer
                    //ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    //Read data from channel
                    socketChannel.read(byteBuffer);
                    byteBuffer.clear();

                    System.out.println(new String(byteBuffer.array()));
                }
                keyIterator.remove();
            }

        }
    }

}

Client

package com.company.Selector.Selector1;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;

public class NIOClient {
    public static void main(String[] args) throws Exception{
        //Open channel
        SocketChannel socketChannel = SocketChannel.open();
        //Set to non blocking
        socketChannel.configureBlocking(false);
        //binding
        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 6666);
        if(!socketChannel.connect(inetSocketAddress)){
            while (!socketChannel.finishConnect()){
                System.out.println("connection failed");
            }
        }
        while (true) {
            Scanner scanner = new Scanner(System.in);
            String str = scanner.nextLine();
            System.out.println(str);

            ByteBuffer byteBuffer = ByteBuffer.wrap(str.getBytes());

            socketChannel.write(byteBuffer);

        }
    }
}

summary

  1. Selector is a selector used to handle non blocking channels, that is, a thread can set a selector to handle multiple channels
  2. Selectors are used to process network channels. The commonly used channels are ServerSocketChannel and SocketChannel. These channels need to be registered on the Selector before they can be managed
  3. The Selector has many methods, among which the select() method monitors all channels. When there are channel events, the SelectionKey object of the channel will be saved to the collection
  4. SelectionKey is an identity object, which holds many properties
Published 81 original articles, won praise 2, visited 2844
Private letter follow

Posted by ulenie on Fri, 06 Mar 2020 22:39:16 -0800