preface

NIO programming is not very familiar, on the one hand, I haven’t studied it systematically, on the other hand, NIO programming is a bit complicated, it is easy to forget after a while, so it is necessary to write a small blog, here to summarize the use of selector components, Buffer and Channel free complement.


Selector

A diagram you may be familiar with (IO multiplexing)



1. What is selector? What’s the use?

A selector, a component of IO multiplexing, and the component directly related to it is a Channel, which constantly polls the channels that are bound to it. Once a channel has an event that it is interested in, the event is processed.


2. A set maintained by selector

Selector maintains three sets of sets that encapsulate the SelectionKey, which is used to get a channel.

2.1 the key set

Each time a channel registers with the selector, a key containing the channel’s own information is added to the set. The registered information is stored in the collection as an encapsulation of the SelectionKey, which is used to retrieve the channel.

2.2 selected key set

SelectionKeys = selectedKeys(); Set

selectionKeys = selectedKeys();

2.3 cannelled key set

The SelectionKey in this collection will be removed from the key set, meaning that the channel associated with it will be discarded by the selector and no longer be listened on.


NIO programming model

1. The server creates a Channel representing the server, binds the port, and sets the Channel as a non-blocking Channel It initializes the selector and then polls the channel bound to itself. The channel has only one ServerSocketChannel, and the selector only cares about OP_ACCEPT events that occur on the ServerSocketChannel and has no client to link to So he’s blocked in select()

/ / the server
// Get the SerSokcetChannel of the server
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
// Set to non-blocking
serverSocketChannel.configureBlocking(false);

// Get the server object from the channel
ServerSocket serverSocket = serverSocketChannel.socket();
serverSocket.bind(new InetSocketAddress(1234));

// Create a selector
Selector selector = Selector.open();
// Register the pass to the selector
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

while (true) {
            // Block to wait for an event to occur on a channel
            int select = selector.select(); 
} 

Copy the code

Select method

select(long); // Set the timeout within which to poll for events of interest (OP_ACCEPT events above)

selectNow(); // Return immediately without blocking

select(); // block pollingCopy the code
  • In the first step, each element in the Cannelled -key is removed from the entire key set, indicating that the channels that can be associated will not be registered
  • Step 2 The operating system polls each channel for something the selector cares about. For a ready channel, it should do at least one of two things:
    • Its key is added to the select-key-set to indicate that it will be selected for processing
    • If its key already exists in the select-key-set, the next step is that its read-operation will be updated
  • Step 3: If any key is found to have been placed in the Cannelled key-set during polling, repeat the first step and not register its associated channels


2. The client creates its own SocketChannel, creates a selector, registers the events it is interested in, and initializes its own SocketChannel, Registers the client channel with the selector and tells the selector that SocketChannel’s event of interest is an OP_CONNECT connection event

// Get the client channel
SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);

Selector selector = Selector.open();
// Register the client channel into the selector
socketChannel.register(selector, SelectionKey.OP_CONNECT);
// Connect to the client. After executing this line of code, the server will be notified
socketChannel.connect(new InetSocketAddress("localhost".1234));

while (true) {
    int number = selector.select(); // The selector blocks and waits for the event it cares about to happen on the Channel
    System.out.println("An event of interest occurred:" + number);
    Set<SelectionKey> keySet = selector.selectedKeys();
/ / verification
    for (SelectionKey selectionKey : keySet) {
        SocketChannel client = null;
if (selectionKey.isConnectable()) {
    // Strong to Channel where connection events occur
    client = (SocketChannel) selectionKey.channel();
    // Complete the connection
    if (client.isConnectionPending()) {
        client.finishConnect();
        ByteBuffer byteBuffer = ByteBuffer.allocate(512);
        byteBuffer.put((LocalDate.now() + "Connection successful").getBytes()); byteBuffer.flip(); client.write(byteBuffer); }}Copy the code