NIO Programming of netty Learning Notes java

Posted by derekbelcher on Mon, 12 Aug 2019 12:50:55 +0200

netty Learning java NIO Programming

NIO in-depth analysis

nio must read and write files through Buffer, read and write state inversion to call. flip() function, read to write, or write state to read, otherwise error will be reported.

2. Whether you read or write, you need a Buffer.

Three attribute elements in Buffer: capacity, limit, position

flip:

Capacity: It means that the number of elements (capacity) contained in Buffer can not be negative. The allocate(n) method determines the size or other methods. After allocation, capacity can not be changed again.


limit: The first element index that cannot be read or written, cannot be negative, cannot exceed its capacity

position: Index of the next element to be read or written <br>

Flp source code:

/**

     * Flips this buffer.  The limit is set to the current position and then

     * the position is set to zero.  If the mark is defined then it is

     * discarded.

     * <p> After a sequence of channel-read or <i>put</i> operations, invoke

     * this method to prepare for a sequence of channel-write or relative

     * <i>get</i> operations.  For example:

     * <blockquote><pre>

     * buf.put(magic);    // Prepend header

     * in.read(buf);      // Read data into rest of buffer

     * buf.flip();        // Flip buffer

     * out.write(buf);    // Write header + data to channel</pre></blockquote>

     * <p> This method is often used in conjunction with the {@link

     * java.nio.ByteBuffer#compact compact} method when transferring data from

     * one place to another.  </p>

     * @return  This buffer
     */

public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
}

The initialized state diagram is as follows, n=6

The following changes occur when four elements are read in

At this point, the flip() function is called, inverted, position returns to the first position, limit comes to the original position, the status is as follows

At this point, you can write up to four elements, and position comes to the limit:

Call flip () again, and postion returns to the first location, with limit unchanged

The clear function reinitializes the Buffer to restore the original starting state. (Data is still there, state migration, reoperation overrides the original data operation, similar to initialization)

rewind function: read again, set limit unchanged, position=0;


Thread Safety: Buffer is not safe in a multi-threaded concurrent environment. If there are multiple threads accessing the environment, synchronization is required.

Synchronized operation.


Three steps to read files through NIO:

  1. Get the FileChannel object from FileInputStream.

  2. Create Buffer

  3. Read data from Channel to Buffer

The meaning of absolute method and relative method:

1. Relative method: limit value and position value will be considered in operation.

2. Absolute method: completely ignoring limit and position values


We can convert an ordinary Buffer to a read-only Buffer at any time, while a read-only Buffer cannot be turned back to the original standard Buffer.

NIO Out-of-heap Memory and Zero Copy

In the Buffer class, there is a long-type field called address, which marks the address of the data to be manipulated by native (operating system layer) outside the java heap and can be directly manipulated by address.

1. The method of HeapByteBuffer is to copy the data on the java heap to an extra space outside the Native heap, and then deal with the IO device. The memory is automatically maintained and recovered by the operating system.
DirectByteBuffer copies the data directly from the heap into Native's data space. No extra copy to another open space is zero copy. Memory recovery of data space is that when DirectByteBuffer is recycled, the address of this out-of-heap space can be found by address address for recovery.

Memory Mapping File

Data can be modified directly in out-of-heap memory, and the interaction between data and IO devices is automatically completed by the operating system.

  public static void main(String []args)throws  Exception{

    RandomAccessFile randomAccessFile=new RandomAccessFile("NioTest9.txt","rw");

    FileChannel fileChannel=randomAccessFile.getChannel();

    //Modify data directly in memory

    //Get the memory mapped object through map

    MappedByteBuffer mappedByteBuffer=fileChannel.map(FileChannel.MapMode.READ_WRITE,0,5);



    //Change element 0 to a

    mappedByteBuffer.put(0,(byte)'a');

    mappedByteBuffer.put(3,(byte)'b');

    randomAccessFile.close();

}

File lock usage

public static void main(String []args)throws  Exception{

    RandomAccessFile randomAccessFile=new RandomAccessFile("NioText10.txt","rw");

    FileChannel fileChannel=randomAccessFile.getChannel();

    //Get the file lock. Lock from the third location, 6 lengths, share lock for ture, exclusive lock for false

    FileLock fileLock=fileChannel.lock(3,6,true);

    System.out.println("valid: "+fileLock.isValid());

    System.out.println("lock type: "+fileLock.isShared());

    //Release lock

    fileLock.release();

    randomAccessFile.close();

}

Network communication of traditional java

It is blocked. Using multi-threaded new Thread technology can solve concurrency easily. A connection creates a new thread, but it wastes a lot of resources. The number of threads per machine has a maximum cpu. (For small-scale applications with fewer users)

NIO Non-blocking Communication

The server can process requests from multiple clients with one thread, and defines a Selector to listen for event events on multiple ports. NIO is event-triggered communication

Selector is important

Instead of introducing the source code here, check it locally.

channel source code for SelectionKey

/**
 * Returns the channel for which this key was created.  This method will
 * continue to return the channel even after the key is cancelled.
 *
 * @return  This key's channel
 */
public abstract SelectableChannel channel();

Examples of using Selector to listen on multiple clients

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NioTest12 {
public static void main(String[]args) throws IOException {
    //Define 5 port numbers for listening
    int []ports=new int[5];
    ports[0]=5000;
    ports[1]=5001;
    ports[2]=5002;
    ports[3]=5003;
    ports[4]=5004;

    Selector selector=Selector.open();
   for (int i=0;i<ports.length;i++){
       ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
       //Configuration is blocked, false-non-blocked
       serverSocketChannel.configureBlocking(false);
       //SerrSocketChannel. socket () returns the socket associated with ServerSocketChannel
       ServerSocket serverSocket=serverSocketChannel.socket();
        //Binding socket address
       InetSocketAddress address=new InetSocketAddress(ports[i]);
       serverSocket.bind(address);

       /**
        * Registers this channel with the given selector, returning a selection
        *  key
        */
       //OP_ACCEPT is interested in connection events and returns the SelectionKey object
       serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("Listening Port: "+ports[i]);
   }

   while (true){
       //Once returned, an event exists in channel
       int numbers=selector.select();
       System.out.println("numbers: "+numbers);

       //Get the corresponding event
       Set<SelectionKey> selectionKeys= selector.selectedKeys();
       System.out.println("selectionKeys: "+selectionKeys);
      Iterator<SelectionKey>iter= selectionKeys.iterator();
      while (iter.hasNext()){
          SelectionKey selectionKey=iter.next();
          if (selectionKey.isAcceptable()){
              //Get ServerSocket Channel
              ServerSocketChannel serverSocketChannel= (ServerSocketChannel) selectionKey.channel();
              SocketChannel socketChannel=serverSocketChannel.accept();
              socketChannel.configureBlocking(false);
                //Pay attention to reading
              socketChannel.register(selector, SelectionKey.OP_READ);
              //Be sure to iter.remove(); indicates that the current event has been used up
              iter.remove();

              System.out.println("Get the client connection:"+socketChannel);
          }else if (selectionKey.isReadable()){//read
                SocketChannel socketChannel= (SocketChannel) selectionKey.channel();
                int bytesRead=0;
                while (true){
                    ByteBuffer byteBuffer=ByteBuffer.allocate(512);
                    byteBuffer.clear();
                    int read=socketChannel.read(byteBuffer);
                    if(read<=0)
                        break;
                    byteBuffer.flip();
                    socketChannel.write(byteBuffer);
                    bytesRead+=read;
                }
                System.out.println("Read: "+bytesRead+" , From: "+socketChannel);
                iter.remove();
          }
      }
   }
}
}

Topics: Java socket network Netty