Comparison of JAVA BIO and NIO

、 、 BIO

1. Mechanism

 The server using the BIO communication model usually has an independent Acceptor thread responsible for monitoring the connection of the client. After it receives the connection request from the client, it creates a new thread for each client request to process the link. After the processing is completed, it outputs the The stream returns the response to the client and the thread is destroyed, which is a typical request-response communication model.

2. Analysis

When the concurrent access of the client increases, the number of threads on the server and the concurrent access of the client increase in a proportional relationship of 1:1. After the threads are expanded, the performance of the system will drop sharply, and even thread stack overflow, creation failure, and eventually Downtime or dying.

Of course, we can use the thread pool on the server side to protect our system from the impact of high concurrency, but even if the thread pool is large, it is limited, so there will be a lot of requests waiting for the resources of the thread pool. Delay and concurrency will still face a very bad situation.

2. NIO

1. Mechanism

Not to mention the concept composition, there are many online.

The server using the nio communication model usually manages one or more channels by an independent thread selector (selector). When the channel registers the selector, the selector will listen to various events of the channel, such as SelectionKey.OP_ACCEPT-receive events , when the registered event occurs, the selected event - SelectionKey is obtained through the iterator. If the SelectionKey is the request connection event, the client's SocketChannel is saved and non-blocking is set, and then the readable listening event is added, so that before the data can be read, the selector You can do some other things; if the SelectionKey is a readable event, you can use the SocketChannel to obtain data through the thread pool, perform the next logical processing, and finally return the response to the client.

2. Analysis

Since the selector can judge the receiving state of the data, it can save the time of waiting for io data, and the time of monitoring the state will be very fast, which can be completed by a single thread, which also avoids the context switching of the thread.

3. Code

1. Server

 

public class NIOServer {  
    //Selector  
    private Selector selector;  
  
    /**
     * Do some initialization work for the channel
     */  
    public void initServer(int port) throws IOException {  
        // Get the ServerSocket channel  
        ServerSocketChannel serverChannel = ServerSocketChannel.open();  
        // set the channel to non-blocking  
        serverChannel.configureBlocking(false);  
        // bind to port  
        serverChannel.socket().bind(new InetSocketAddress(port));  
        // get selector  
        this.selector = Selector.open();  
        //Register the SelectionKey.OP_ACCEPT event for this channel
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);  
    }  
  
    /**
     * Use polling to monitor whether there are events that need to be processed on the selector, and if so, process them
     */  
    @SuppressWarnings("unchecked")  
    public void listen() throws IOException {  
        // polling access selector  
        while (true) {  
            //When the registered event arrives, the method returns; otherwise, the method will always block  
            selector.select();  
            // Get the iterator of the selected item in the selector, the selected item is the registered event  
            Iterator ite = this.selector.selectedKeys().iterator();  
            while (ite.hasNext()) {  
                SelectionKey key = (SelectionKey) ite.next();  
                // delete the selected key to prevent repeated processing  
                ite.remove();  
                // client request connection event
                if (key.isAcceptable()) {
  
                    ServerSocketChannel server = (ServerSocketChannel) key  
                            .channel();  
                    // Get the channel to connect to the client  
                    SocketChannel channel = server.accept();  
                    // set to non-blocking  
                    channel.configureBlocking(false);  
  
                    // can send information to the client  
                    channel.write(ByteBuffer.wrap(new String("abc").getBytes()));  
                    //After the connection with the client is successful, in order to receive the client's information, the read permission needs to be set for the channel.  
                    channel.register(this.selector, SelectionKey.OP_READ);  
                      
                      
                } else if (key.isReadable()) {
                        // get readable events
                        read(key);  
                }  
  
            }  
  
        }  
    }  
    /**
     * Processing logic
     */  
    public void read(SelectionKey key) throws IOException{  
        // The server can read the message: get the Socket channel where the event occurred  
        SocketChannel channel = (SocketChannel) key.channel();  
        // create read buffer  
        ByteBuffer buffer = ByteBuffer.allocate(10);  
        channel.read(buffer);  
        byte[] data = buffer.array();  
        String msg = new String(data).trim();  
        System.out.println("Server received message: "+msg);  
        ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes());  
        channel.write(outBuffer);// Send the message back to the client  
    }  
      
    /**
     * Start the server test  
     */  
    public static void main(String[] args) throws IOException {  
        NIOServer server = new NIOServer();  
        server.initServer(8000);  
        server.listen();  
    }  
  
}

 2. Client

public class NIOClient {  
    //Selector  
    private Selector selector;  
  
    /**
     * Do some initialization work for the channel
     */  
    public void initClient(String ip,int port) throws IOException {  
        // Get a Socket channel  
        SocketChannel channel = SocketChannel.open();  
        // set the channel to non-blocking  
        channel.configureBlocking(false);  
        // Selector
        this.selector = Selector.open();  
          
        // The client connects to the server. In fact, the method execution does not realize the connection. It needs to be adjusted in the listen() method.  
        //Use channel.finishConnect(); to complete the connection  
        channel.connect(new InetSocketAddress(ip,port));  
        //Bind the channel manager to the channel and register the SelectionKey.OP_CONNECT event for the channel.  
        channel.register(selector, SelectionKey.OP_CONNECT);  
    }  
  
    /**
     * Use polling to monitor whether there are events that need to be processed on the selector, and if so, process them
     */  
    @SuppressWarnings("unchecked")  
    public void listen() throws IOException {  
        // polling access selector  
        while (true) {  
            selector.select();  
            // Get the iterator of the selected items in the selector  
            Iterator ite = this.selector.selectedKeys().iterator();  
            while (ite.hasNext()) {  
                SelectionKey key = (SelectionKey) ite.next();  
                // delete the selected key to prevent repeated processing  
                ite.remove();  
                // connect event occurs  
                if (key.isConnectable()) {  
                    SocketChannel channel = (SocketChannel) key  
                            .channel();  
                    // If connecting, complete the connection  
                    if(channel.isConnectionPending()){  
                        channel.finishConnect();  
                          
                    }  
                    // set to non-blocking  
                    channel.configureBlocking(false);  
  
                    //You can send information to the server here  
                    channel.write(ByteBuffer.wrap(new String("abc").getBytes()));  
                    //After the connection with the server is successful, in order to receive the information from the server, you need to set the read permission for the channel.  
                    channel.register(this.selector, SelectionKey.OP_READ);  
                      
                    // get readable events  
                } else if (key.isReadable()) {  
                        read(key);  
                }  
  
            }  
  
        }  
    }
 
    /**
     * Processing logic
     */  
    public void read(SelectionKey key) throws IOException{  
        SocketChannel channel = (SocketChannel) key.channel();  
        // create read buffer  
        ByteBuffer buffer = ByteBuffer.allocate(10);  
        channel.read(buffer);  
        byte[] data = buffer.array();  
        String msg = new String(data).trim();  
        System.out.println("Client received message: "+msg);   
    }  
      
    /**
     * Start client test  
     */  
    public static void main(String[] args) throws IOException {  
        NIOClient client = new NIOClient();  
        client.initClient("localhost",8000);  
        client.listen();  
    }  
}  

  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326081469&siteId=291194637