"Netty Source 1" Introducing Network IO

Channel

IO Operations Link, where a Channel represents an open connection to an entity. In network IO, it is usually used to read/write data with Buffer.

Implementations of some of the major Channel s in JAVA NIO

  • FileChannel: Read and write data from a file.
  • DatagramChannel: Can read and write data in the network through UDP.
  • SocketChannel: Can read and write data in the network over TCP.
  • ServerSocketChannel: Can listen for new incoming TCP connections like Web servers. A SocketChannel is created for each new connection.

common method

  • int read(ByteBuffer var1) read bytes from Buffer
  • int write(ByteBuffer src) writes data to Buffer
  • boolean connect(SocketAddress remote) client connects to an address
  • SocketChannel accept() accepts connections and creates SocketChannel

Buffer

Buffer is essentially a piece of memory that can write data and then read it. This block of memory is packaged as a NIO Buffer object and provides a set of methods for accessing it easily.

Key Buffer implementations in Java NIO

These implementations basically cover the basic data types for all IO transmissions

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

common method

  • ByteBuffer allocate(int capacity): Create a buffer of a specified size
  • ByteBuffer put(byte b): Writes the specified byte to the buffer, and read for the channel writes the channel's data to the buffer
  • byte get(): read data from buffer, write of channel writes data from buffer to channel
  • Buffer flip() read-write mode switch

Selector

Selector (Multiplexer). It is one of the core components of Java NIO and listens on multiple Channels at the same time. When a particular event occurs on a channel, these channels become available.

common method

  • public static Selector open(): Create selector
  • The final SelectionKey register(Selector sel, int ops) method is channel, the selector is passed in as a parameter, and the second parameter is in, an event. When a channel triggers an event, it becomes ready. These four events are
    • SelectionKey.OP_READ:: Read events for both ends
    • SelectionKey.OP_WRITE:: Write time, for both ends
    • SelectionKey.OP_CONNECT:: Connection Completion Event (TCP Connection), applicable only to clients
    • SelectionKey.OP_ACCEPT:: Accept new connection events, only for server side
  • Set selectedKeys(): Returns the corresponding SelectionKeys
  • int select(): blocked to a channel ready, how many channels are returned ready
  • int select(long timeout): increase timeout mechanism
  • public abstract int selectNow(): Returns the quantity immediately without blocking.

SelectionKey

SelectionKey represents a token registered by a channel to a selector

common method

  • SelectionKey interestOps(): Returns a collection of events of interest
  • Object attach(Object ob): Add an attachment to the SelectionKey
  • Object attachment(): Take the attachment out of SelectionKey

SocketChannel

SocketChannel is the channel that connects to a TCP network socket.
Created as SocketChannel.open or ServerSocketChannel.accept(), described above, repeated below

ServerSocketChannel

ServerSocketChannel is the channel that listens for new incoming TCP connections

Traditional IO Programming [Simplified Version]

Now that you know these basic concepts, let's start with the Network Programming section, which starts with a simple example.

Server

public class NIOServer {
    public static void main(String[] args) throws IOException {
        //Create ServerSocketChannel to handle access connections
        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
        //Set whether to be non-blocking
        serverSocketChannel.configureBlocking(false);
        //Binding Port Number
        serverSocketChannel.socket().bind(new InetSocketAddress(8080));
        while (true){
            if(serverSocketChannel.isOpen()){
                SocketChannel socketChannel=serverSocketChannel.accept();
                if(socketChannel!=null){
                    //Read data
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int bytesRead = socketChannel.read(buffer);
                    buffer.flip();
                    byte[] bytes = new byte[buffer.remaining()];
                    System.arraycopy(buffer.array(), buffer.position(), bytes, 0, buffer.remaining());
                    System.out.println(new String(bytes, "UTF-8"));
                    //Channel closure
                    socketChannel.close();
                }
            }
        }
    }
}

Client

public static void main(String[] args) throws IOException, InterruptedException {
    for (int i = 0; i < 30; i++) {
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress(8080));
        if(socketChannel.isConnected()){
            ByteBuffer buffer=ByteBuffer.allocate(1024);
            buffer.put("hello world".getBytes());
            System.out.println("hello world");
            buffer.flip();
            while(buffer.hasRemaining()) {
                socketChannel.write(buffer);
            }
            socketChannel.close();
        }

    }
}

Is simply sending data


Then the problem comes. It's a simple network programming, but there are still many problems. For example, the server can only process new connections and the first received information, but it can't process subsequent sent data. There are still many problems. Here we use Selector, optimized for this example

Traditional IO programming

Server

public class NIOServer2 {
    public static void main(String[] args) throws IOException {
        //Create ServerSocketChannel to handle access connections
        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
        //Create Selector
        Selector selector=Selector.open();
        //Set whether to be non-blocking
        serverSocketChannel.configureBlocking(false);
        //Create registered channel s into selector creation connection time
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        //Binding Port Number
        serverSocketChannel.socket().bind(new InetSocketAddress(8080));
        while (true){
            if(serverSocketChannel.isOpen()){
                // Select Channel through Selector
                int selectNums = selector.select(1000L);
                if (selectNums == 0) {
                    continue;
                }
                // Traverse the SelectionKey collection of selectable Channel s
                for (SelectionKey selectKey:selector.selectedKeys()) {
                    // Ignore invalid SelectionKey
                    if (!selectKey.isValid()) { 
                        continue;
                    }
                    //New Connection Created
                    if(selectKey.isAcceptable()){
                        //Get the channel created by the new connection
                        SocketChannel socketChannel= ((ServerSocketChannel) selectKey.channel()).accept();
                        if(socketChannel!=null){
                            //Set to non-blocking
                            socketChannel.configureBlocking(false);
                            //Register with selector
                            socketChannel.register(selector,SelectionKey.OP_READ);
                        }
                    }
                    //Processing Read Time
                    if(selectKey.isReadable()){
                        SocketChannel socketChannel= (SocketChannel) selectKey.channel();
                        if(socketChannel!=null){
                            //Read data
                            ByteBuffer buffer = ByteBuffer.allocate(1024);
                            int bytesRead = socketChannel.read(buffer);
                            if(bytesRead==-1){
                                socketChannel.register(selector,0);
                                socketChannel.close();
                            }else{
                                buffer.flip();
                                byte[] bytes = new byte[buffer.remaining()];
                                System.arraycopy(buffer.array(), buffer.position(), bytes, 0, buffer.remaining());
                                System.out.println(new String(bytes, "UTF-8"));
                            }

                        }
                    }
                }
            }
        }
    }
}

Client

public static void main(String[] args) throws IOException, InterruptedException {
    SocketChannel socketChannel = SocketChannel.open();
    socketChannel.connect(new InetSocketAddress(8080));
    for (int i = 0; i < 30; i++) {

        if(socketChannel.isConnected()){
            ByteBuffer buffer=ByteBuffer.allocate(1024);
            buffer.put("hello world".getBytes());
            System.out.println("hello world");
            buffer.flip();
            while(buffer.hasRemaining()) {
                socketChannel.write(buffer);
            }
        }

    }
    socketChannel.close();

}

It is now possible to handle different events differently

Reference Article
http://ifeve.com/java-nio-all/

Keywords: Java Netty

Added by ('(' on Sun, 24 Oct 2021 19:39:57 +0300