Happy Children’s Day, everyone. I am Xiao Hei.

Today I’m going to share with you the blocking IO model in network programming. There are five common IO models in network programming: synchronous blocking IO model, synchronous non-blocking IO model, multiplexing IO model, signal-driven IO model and asynchronous IO model. This blog will share the blocking IO model for the time being, and other IO models will be updated in subsequent blogs.

What is the synchronous blocking IO model

In network transmission, data is transferred to the machine through the computer network until the program reads the data, which goes through two steps:

  • Data is copied from the nic to the kernel space
  • Data is copied from kernel space to user space for application to read

The difference between IO models is the way these two steps work. Synchronous blocking IO is done by user thread initiationread()The call blocks, freeing up the CPU. The kernel waits for the nic data to arrive, copies the data from the NIC to kernel space, then copies the data to user space, and wakes up the user thread. The whole process is blocked, as shown in the figure.

Implementation of single-line synchronous blocking IO model

Here is the simplest implementation of a single-threaded version of the blocking IO model, but it is small.

The example is an Echo server, where whatever data the client sends, the server adds a date and returns it as it is.

Let’s take a look at how to implement the server side, the code is as follows. The body is an infinite loop that blocks on the Accept () method until a connection is established. Upon return, the handle() method is called for processing, which generally consists of three major steps: reading client data; Processing client data; The result is returned to the client.

public class EchoServer {

    private ServerSocket serverSocket;

    public static void main(String[] args) throws IOException {
        new EchoServer().start();
    }

    public EchoServer(a) throws IOException {
        serverSocket = new ServerSocket(8001); // Initialize a ServerSocket and bind port 8001
    }

    public void start(a) {

        for(; ;) { Socket socket =null;
            try {
                socket = serverSocket.accept(); // A client connection is received
                handle(socket); Read ->process->write
            } catch(IOException e) { e.printStackTrace(); }}}private void handle(Socket socket) {
        BufferedReader bufferedReader = null;
        PrintWriter printWriter = null;
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            printWriter = new PrintWriter(socket.getOutputStream(), true);
            String line = null;
            while((line = bufferedReader.readLine()) ! =null) { // read Reads client data
                String echoMsg = new Date() + ":" + line; // process processes client data
                printWriter.println(echoMsg); // write The result is returned to the client}}catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (Objects.nonNull(printWriter)) {
                    printWriter.close();
                }
                if (Objects.nonNull(bufferedReader)) {
                    bufferedReader.close();
                }
                socket.close();
            } catch(IOException e) { e.printStackTrace(); }}}}Copy the code

Take a look at the client code. It first connects to the server, then reads the data from the console and sends it to the server, and waits for the server to respond.

public class EchoClient {

    private Socket socket;

    public EchoClient(a) {
        socket = new Socket();
    }

    public static void main(String[] args) throws IOException {
        new EchoClient().start();
    }

    public void start(a) throws IOException {


        socket.connect(new InetSocketAddress("localhost".8001)); // Establish a connection
        try {
            BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in));
            InputStream in = socket.getInputStream();
            OutputStream out = socket.getOutputStream();
            BufferedReader bufReader = new BufferedReader(new InputStreamReader(in));
            PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(out), true);
            String msg = null;
            while((msg = localReader.readLine()) ! =null) {
                printWriter.println(msg); // Send data
                System.out.println(bufReader.readLine()); // Accept the response}}catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(Objects.isNull(socket)) { socket.close(); }}}}Copy the code

An example of this running is shown below, where the green font is the data entered by the client on the console and the black font is the data responded by the server.

What are the problems with the single-threaded version of synchronous blocking IO model

We can start one EchoServer and start multiple EchoClients in parallel to see what the problems are with the single-threaded version of the synchronous blocking IO model. EchoServer has only one thread, which alone reads the client data, processes the business, and sends the response back to the client (write). Any of the intermediate steps may block or occupy a large amount of CPU time. If there are more than one connection, the whole server is bound to block many client connections, affecting communication performance.

In reality, there are many practical applications requiring the server to provide services for multiple clients at the same time, such as the HTTP server we use every day, if too many clients cause a long wait, it will make the website lose credibility, thus reducing the number of visits. So the problem with the single-threaded version of the synchronous blocking IO model is that it is single-threaded and does not take full advantage of the multithreading capabilities of today’s machines to handle multiple user requests in parallel.

To solve this problem, use multithreading, as detailed in the next article: The Synchronous blocking IO model – Multithreading version, to be updated soon.

In vain.

Ref

  • Geek time: inside dismantling Tomcat&Jetty
  • Sun Weiqin: The Essence of Java Network Programming
  • Budi Kurniawan, Paul Deck: Inside Tomcat
  • Ge Yiming: Practical Java High Concurrency Programming