A preface
With the deepening of learning, Le Le gradually can better understand and learn through the code at the same time to query some information
Comparative advantages of two IO models
The most obvious advantage of NIO is the traditional BIO. A server socket is directly connected to a client socket, and the server needs to create a new thread for each client to handle the communication between the client, which inevitably costs a lot of resources on the server.
Our NIO can access tens of thousands or more client connections with only one selector and one polling thread, which is the biggest improvement and change from BIO. The second is the way to establish the connection. In traditional BIO, the client server establishes the TCP connection through the three-way handshake, while in NIO, the client directly registers the channel with the server multiplexer, and then the server polls, which reduces the overhead of the three-way handshake request response. Again is the direct buffer code stream, traditional bio request and response data is read by side to create the output stream directly to the other end of the output, while the other DianChuan write data input stream, it is depend on the network, if the network is bad can lead to do so time is not closed, resulting in resource waste and a cause increased costs. Nio introduced the buffer to write data and write data directly to the buffer, so it doesn’t depend on the network. One end can write data to the buffer and then close the write stream, so you just need to tell the other end to read. The other end turns on the read stream and quickly reads the buffer’s data, which can then be quickly closed. If the network is not good, it will not spend resources on the other side.
Iii Code Practice
- BIO
-
The service side
try { serverSocket = new ServerSocket(); serverSocket.bind(new InetSocketAddress(7397)); System.out.println("itstack-demo-netty bio server start done."); while (true) { Socket socket = serverSocket.accept(); BioServerHandler handler = new BioServerHandler(socket, Charset.forName("GBK")); handler.start(); } } catch (IOException e) { e.printStackTrace(); } Copy the code
-
The client
Try {Socket Socket = new Socket("127.0.0.1", 7397); System.out.println("itstack-demo-netty bio client start done."); BioClientHandler bioClientHandler = new BioClientHandler(socket, Charset.forName("utf-8")); bioClientHandler.start(); } catch (IOException e) { e.printStackTrace(); }Copy the code
From the point of view of the code is very simple, one-to-one direct connection, first create in the binding and accept three steps, but multiple connections to open multiple threads
2.NIO
-
The service side
Try {// open selector = selector. Open (); SocketChannel = serverSocketChannel.open (); / / set the channel to a non-blocking socketChannel. ConfigureBlocking (false); Socketchannel.socket ().bind(new InetSocketAddress(port), 1024); // Register the server channel with the multiplexer and listen for the blocking event socketChannel.register(selector, selectionkey.op_accept); System.out.println("itstack-demo-netty nio server start done."); new NioServerHandler(selector, Charset.forName("GBK")).start(); } catch (IOException e) { e.printStackTrace(); }Copy the code
-
The client
Selector selector = Selector.open(); SocketChannel socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); boolean isConnect = socketChannel.connect(new InetSocketAddress("192.168.1.116", 7397)); if (isConnect) { socketChannel.register(selector, SelectionKey.OP_READ); } else { socketChannel.register(selector, SelectionKey.OP_CONNECT); } System.out.println("itstack-demo-netty nio client start done. "); new NioClientHandler(selector, Charset.forName("GBK")).start(); Copy the code
Now it’s easier to understand. The BIO used to be directly connected. Now NIO comes up with an intermediate layer, which is kind of like a cloud disk, where you upload all the data that the server needs to upload. You don’t have to wait until there’s a connection.
3.AIO
-
The service side
try { serverSocketChannel = AsynchronousServerSocketChannel.open(AsynchronousChannelGroup.withCachedThreadPool(Executors.newCachedThreadPool(), 10)); serverSocketChannel.bind(new InetSocketAddress(7397)); System.out.println("itstack-demo-netty aio server start done. "); // 等待 CountDownLatch latch = new CountDownLatch(1); serverSocketChannel.accept(this, new AioServerChannelInitializer()); latch.await(); } catch (Exception e) { e.printStackTrace(); } Copy the code
We’ll start with the CountDownLatch class. This class is a counter that controls when multiple threads access a resource. Its function is that it has to wait until everything else is thought to be finished before it can execute the resource below it, so it initializes itself as 1 and then it waits to execute the “await” resource before it can execute the next one.
-
The client
AsynchronousSocketChannel socketChannel = AsynchronousSocketChannel.open(); Future<Void> Future = Socketchannel.connect (new InetSocketAddress("127.0.0.1", 7397)); System.out.println("itstack-demo-netty aio client start done."); future.get(); socketChannel.read(ByteBuffer.allocate(1024), null, new AioClientHandler(socketChannel, Charset.forName("GBK"))); Thread.sleep(100000);Copy the code
The client uses the Future, which is non-blocking, so it can perform the following functions without waiting for the result to return, but if I want to return the result, I have to call future.get(), which will return the result. This class is quite unique and can be different. AIO is asynchronous non-blocking, and its non-blocking is embodied in the Future.