• J3 – leitian
  • Technology (I/O flow)

I’ve been reading about Netty, and I’ll be writing about some Netty related technologies in the future.

As Netty is one of the most popular NIO frameworks in the industry, it is natural to start with a comprehensive introduction to BIO, NIO, and AIO.

So before we get started on Netty, LET me introduce you to the basic I/O architecture to build on the appeal of Netty.

What is flow

Baidu Concept:

A stream is an ordered collection of bytes with a starting point and an ending point. It is a general term or abstraction for data transmission. The transmission of data between two devices is called a stream. The essence of a flow is data transmission. According to the data transmission characteristics, a flow is abstracted into various classes to facilitate more intuitive data operations.

The bottom line is: == streams are transmissions, and the contents of transmissions are bytes ==

In Java, we often say byte stream and character stream are essentially two operations divided into different streams of content. Byte stream operations are in bytes and character stream operations are in characters.

As mentioned earlier, a flow has a beginning and an end. And because the starting point and end point are different, the flow can be divided into: input flow, output flow.

To understand:

Memory -> Hard disk = OutputStream, Writer

Hard disk -> memory = InputStream (InputStream, Reader)

Java provides a number of API operations for stream operations, package locations: java.io, java.nio.

Because this article is not to teach you how to use the API, so it is not much introduction, but I am not the kind of irresponsible man 😀, I have found you to review the IO stream operation of the basic tutorial 👉👉👉 click here.

In order to introduce BIO, NIO, and AIO concepts, a small example should be written below:

@Slf4j
public class BioTest {

    /** * streams the file */
    @Test
    public void streamTest(a) throws Exception {

        // Define two files, in.txt and out.txt.
        File inFile = new File("src/in.txt");
        File outFile = new File("src/out.txt");

        // Define a stream object that operates on in.txt
        InputStream inputStream = new FileInputStream(inFile);
        // Start reading the file
        byte[] bytes = new byte[8];
        inputStream.read(bytes);
        System.out.println(new String(bytes));

        // Define the stream object for the out.txt operation
        OutputStream outputStream = new FileOutputStream(outFile);
        // Start writing out the file
        outputStream.write(bytes);
        outputStream.write("\nout-write".getBytes(StandardCharsets.UTF_8));

    }

    /** * blocking form of operation network programming */
    @Test
    public void blockTest(a) throws Exception {
        / * 1, running the service side found, the service side in obtaining client connection and the access to client data, can jam * /
    }

    @Test
    public void server(a) throws Exception {
        // Create a server object
        ServerSocket serverSocket = new ServerSocket(9528);
        log.info("Created a server object,{}", serverSocket);
        // Get the soclet object for the client link
        Socket accept = serverSocket.accept();
        log.info("Got the client connection object,{}", accept);
        InputStream inputStream = accept.getInputStream();
        byte[] bytes = new byte[100];
        inputStream.read(bytes);
        log.info("Content sent from client: {}".new String(bytes));
    }

    @Test
    public void client(a) throws Exception {
        // Create a client, specify the IP address and port of the server, and connect to the client
        Socket client = new Socket("localhost".9528);
        log.info("Client created,{}", client);
        // Start sending messages to the server
        OutputStream outputStream = client.getOutputStream();
        outputStream.write("hello world!".getBytes(StandardCharsets.UTF_8)); }}Copy the code

The above example shows two effects, first-class operation and double-blocking operation.

Streams and blocking are a poor representation of Java’s traditional IO (BIO). Streams are not as efficient at transporting data as buffers with channels; And blocking is even worse than a non-blocking Selector.

Second, the BIO

Synchronous blocking in I/O mode, data reads and writes must be blocked in a thread waiting for them to complete.

It was also the only IO mode available prior to Java 1.4.

There are two nouns: synchronization and blocking, so let me explain.

noun explain example
synchronous A user process triggers an I/O operation and waits or polls to see if the OPERATION is ready Helpless painful course single programmer A, to be able to find blind date object to go to work every day to come off work search each big single little sister contact means, this kindDo your own work and ignore your workIt’s synchronization.
asynchronous Asynchronous means that the user process starts to do its own work after the I/O operation is triggered. When the I/O operation is completed, the user process will be notified of the COMPLETION of the I/O operation. Smart and flexible single programmer B, in order to find a variety of dating little sister’s contact information, directly contacted a large matchmaking company, by the matchmaking company to get the contact information of little sister, this kind ofDelegate form without delay normal workIt’s asynchronous.
blocking Blocking means that when attempting to read or write to the file descriptor, if there is nothing to read or write to at the moment, the program enters a waiting state until there is something to read or write to Programmer A, finally found several good shape conditions of the little sister, but has been unable to date someone else, can only wait for their free time,This waiting is called blocking.
non-blocking In a non-blocking state, if there is nothing to read or write to, the read-write function returns immediately, without waiting Programmer B, because it is a large matchmaking company, find contact information, and certainly dating dating one-stop service, so smooth and little sister meet to talk about life to talk about ideal… , this kind ofThe direct contract is non-blocking.

From the code examples I wrote above and this table, I believe you have a very clear understanding of synchronization and blocking. Let’s look at the BIO model below:

As can be seen from the figure, A server corresponds to multiple clients, each of which is facing different threads. As A result, when client A communicates with the server in A single-threaded environment, both B and C need to wait for blocking, and only after A finishes communicating with client B and C can proceed with subsequent steps.

For the case code, see section 1.

Third, the NIO

Synchronous non-blocking I/O mode, which has been supported since Java 1.4, provides abstractions like channels, selectors, and buffers (we’ll focus on these three components later).

We all know that traditional BIO is stream-oriented, but NIO realized the efficiency of streams and proposed a buffer-oriented (block-oriented) approach to IO operations, which greatly improves the efficiency of transport.

NIO also provides two different Socket channel implementations, SocketChannel and ServerSocketChannel, corresponding to Socket and ServerSocket in the traditional BIO model. Both channels support blocking and non-blocking modes. Blocking mode, like traditional support, is relatively simple, but has poor performance and reliability. Non-blocking mode is the opposite. For low-load, low-concurrency applications, synchronous blocking I/O can be used for faster development and better maintenance; For high-load, high-concurrency (network) applications, NIO’s non-blocking mode should be used for development.

The NIO model is shown as follows:

Case study:

@Slf4j
public class NioTest {

    @Test
    public void serverTest(a) throws Exception{
        / / create a serverSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // Bind ports
        serverSocketChannel.socket().bind(new InetSocketAddress(6666));
        // Set it to non-blocking
        serverSocketChannel.configureBlocking(false);
        // Get the Selector object
        try (Selector selector = Selector.open()) {
            // Register ServerSocketChannel with selector, event OP_ACCEPT
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            // If >0 is returned, the concerned event has been retrieved
            while (selector.select() > 0) {
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    // Get an event
                    SelectionKey next = iterator.next();
                    // If it is OP_ACCEPT, there is a new client connection
                    if (next.isAcceptable()) {
                        // Generate a SocketChannel for the client
                        SocketChannel accept = serverSocketChannel.accept();
                        accept.configureBlocking(false);
                        // Register the current socketChannel with the selector, focus on the event as a read event, and associate a buffer with the socketChannel
                        accept.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                        log.info("Obtained a client connection");
                        // If it is read event
                    } else if (next.isReadable()) {
                        // Obtain the corresponding channel through the key
                        SocketChannel channel = (SocketChannel) next.channel();
                        // Get the buffer associated with the channel
                        ByteBuffer buffer = (ByteBuffer) next.attachment();
                        while(channel.read(buffer) ! = -1) {
                            buffer.flip();
                            log.info(new String(buffer.array(), 0, buffer.limit())); buffer.clear(); }}// It is important to remove the event after it has been processediterator.remove(); }}}}@Test
    public void clientTest(a) throws Exception{
        // Get a network channel
        SocketChannel socketChannel = SocketChannel.open();
        // Set it to non-blocking
        socketChannel.configureBlocking(false);
        // Provide the IP address and port of the server
        InetSocketAddress inetSocketAddress = new InetSocketAddress("localhost".9528);
        // Connect to the server
        if(! socketChannel.connect(inetSocketAddress)) {while(! socketChannel.finishConnect()) { log.info("Connections take time, clients don't block... You can go do something else."); }}// The connection is successful and data is sent
        String str = "J3 - leitian";
        ByteBuffer byteBuffer = ByteBuffer.wrap(str.getBytes());
        socketChannel.write(byteBuffer);
        socketChannel.close();
        log.info("Client exit"); }}Copy the code

This code, can reflect the server to obtain the client connection does not need to block, and when reading the data sent by the client does not need to block there is no data read down, which is one of the reasons for the popularity of Netty framework.

Four, AIO

Asynchronous non-blocking I/O mode, an improved version of NIO, NIO 2, was introduced in Java 7.

Asynchronous IO is implemented based on events and callbacks, meaning that an action is applied and returned, not blocked, and when the background processing is complete, the operating system notifies the appropriate thread to proceed with the subsequent action.

For AIO online information is not a lot, and the application is not very wide, so…

Five, the last

The purpose of this article is to give you a general understanding of the Java IO model architecture, know BIO, NIO, AIO this thing and understand the difference between synchronization, blocking line.

For the specific application, I did not elaborate, because BIO is the basic I have posted the tutorial address ☝☝☝. And NIO is the premise of learning Netty, I will continue to output this part later, as for AIO application is not very widespread, I will not, so you can not pay attention to understand the line.

All right, so that’s NIO for the next one. Follow me and I’ll see you next time.

Access to or Extension of information:

  • Netty’s Definitive Guide, Second Edition

  • Ramblings: How to Explain the Five IO Models of Linux to your Girlfriend?

  • www.zhihu.com/question/64…

  • Segmentfault.com/a/119000003…


  • Due to the lack of knowledge of the blogger, there will be mistakes, if you find mistakes or bias, please comment to me, I will correct it.

  • If you think the article is good, your retweets, shares, likes and comments are the biggest encouragement to me.

  • Thank you for reading. Welcome and thank you for your attention.

^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^

CSDN:J3 – leitian

The nuggets:J3 – leitian

Zhihu:J3 – leitian

This is a technical average, but keen to share; Inexperienced but thick-skinned; Young and good-looking programmers who insist on talent for a living.

^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^