IO of JAVA IO – API

Network IO programming steps

NIO

  1. Create a listener that allows a client to initiate a request
  2. After binding network Socket ports, an important step is to check whether services need to be set to block the OS
  3. Accept () in an infinite loop
  4. Read the data
public class ServerNIO { public static void main(String[] args) { ServerNIO nio = new ServerNIO(); ServerSocketChannel socketChannel = nio.inintServer(); while (true){ nio.getMsg(socketChannel); Private ServerSocketChannel inintServer(){ServerSocketChannel Server = null; Try {//NIO Channel create listener server = serverSocketChannel.open (); // Bind port 9999 server.bind(new InetSocketAddress(9999)); // Set OS NONBLOCKING server.configureBlocking(false); System.out.println(" Server started "); } catch (IOException e) { e.printStackTrace(); } return server; } private void getMsg(ServerSocketChannel ServerSocketChannel){try {// The server receives requests from the client SocketChannel client = serverSocketChannel.accept(); if (client ! =null){// Set client to a non-blocking client.configureBlocking(false); / / optimize performance increase buffer ByteBuffer buffer = ByteBuffer. AllocateDirect (2048); Int read = client.read(buffer); If (read>0){// Switch the read/write mode buffer.flip(); byte[] aaa = new byte[buffer.limit()]; buffer.get(aaa); String b = new String(aaa); System.out.println(client.socket().getPort() + " : " + b); buffer.clear(); } } } catch (IOException e) { e.printStackTrace(); }}}Copy the code

The key to multiplexing is the introduction of the Selector selector, which processes I/O requests in batches

package nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.util.Iterator; import java.util.Set; /** * @Classname SocketMultiplexingSingleThread * @Description TODO * @Date 2020/12/23 10:34 AM * @Author by lixin */ public class SocketMultiplexingSingleThread { private ServerSocketChannel server =null; private Selector selector=null; Private void initServer(){try {// Create channel listener server =ServerSocketChannel.open(); // Bind port 8888 server.bind(new InetSocketAddress(8888)); // Set OS NONBLOCKING server.configureBlocking(false); Epoll_create ->fd */ selector = poll_create ->fd */ selector = Selector.open(); // The server registers with the multiplexer and declares events. /* select * from the JVM, poll: Epoll_ctl (fd3,ADD,fd4,EPOLLIN,EPOLLIN, epoll_ctl) creates two more spatial red black trees (all epoll_ctl commands store FD in the tree) and statically linked list result set */ server.register(selector, SelectionKey.OP_ACCEPT); } catch (IOException e) { e.printStackTrace(); } } public void getMsg() throws IOException { initServer(); System.out.println(" Server started "); While (true){// Loop to see if any messages come in /* 1. Selector. Select () (which increases the blocking time) Poll select (fd) poll(fd) */ while (selector. Select ()>0){// Retrieve all events from selector /* */ Set<SelectionKey> keys = selectedKeys(); */ Set<SelectionKey> keys = selector. Iterator<SelectionKey> iterator = keys.iterator(); while (iterator.hasNext()){ SelectionKey key = iterator.next(); // **** events that are processed need to be removed. If they are not removed, they will be processed in a loop. **** iterator.remove(); If (key.isacceptable ()){if (key.isacceptable ()){if (key.isacceptable ()){if (key.isacceptable ()){if (key.isacceptable ()){if (key.isacceptable ()){if (key.isacceptable ()){if (key.isacceptable ()){ We register acceptHandler(key) in the kernel space with epoll_ctl; }else if (key.isreadable ()){// Note that read is often blocked for various things, such as a minute, an hour, or even a year, so that the system cannot be used by others. IO Threads the same idea is present in Redis. Redis has the concept of readHandler(key) for IO Threads because it is a single thread. } //... }}}} private void readHandler(SelectionKey key) {// Read data from client SocketChannel client = (SocketChannel) key.channel(); // client.register(selector,SelectionKey.OP_READ,buffer); //ByteBuffer buffer = (ByteBuffer) key.attachment(); Buffer = (ByteBuffer) key.attachment(); // Pairs of buffers are registered with the selector and read with attachment(). buffer.clear(); int read= 0; try { while (true){ read = client.read(buffer); if (read>0){ buffer.flip(); while (buffer.hasRemaining()) { client.write(buffer); } buffer.clear(); }else if (read == 0) { break; } else { client.close(); break; } } } catch (IOException e) { e.printStackTrace(); }} private void acceptHandler(SelectionKey key) {// Obtain the ServerSocketChannel ServerSocketChannel = (ServerSocketChannel) key.channel(); Try {/ / from the server receives the new client SocketChannel client = serverSocketChannel. The accept (); client.configureBlocking(false); ByteBuffer buffer = ByteBuffer.allocate(8192); Register (selector, selectionkey. OP_READ,buffer); System.out.println("-------------------------------------------"); System.out.println(" new client: "+ client.getremoteAddress ()); System.out.println("-------------------------------------------"); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { SocketMultiplexingSingleThread sevice = new SocketMultiplexingSingleThread(); sevice.getMsg(); }}Copy the code

Extreme version of multiplexing elite API, to tell you about the idea

  1. In order to take full advantage of the multi-core CPU, we can keep the CPU as busy as possible. The ideal number of threads is the number of CPU cores or twice the number of CPU cores
  2. We can use multiple threads, create multiple selectors, one for each thread
  3. We can mix to handle events, or we can specify a selector to handle only receiving clients
  4. Another selector handles W/R events, and this idea is very close to Netty and if we could write it out by hand it would give us a good foundation for netty later on