This article brings you relevant knowledge about java, which mainly introduces NIO-related issues, including NIO core, comparison between BIO and NIO, and implementation of simple server clients through NIO Terminal communication, I hope it will be helpful to everyone.
## Recommended study: "java Tutorial"
1. Java Mind Map 2. I/O modelThe essence of the I/O model is what kind of channel is used to send and receive data, which largely determines the performance of program communication. Java supports three network programming models: BIO, NIO, AIO
NIO is buffer-oriented, or block-oriented programming. The data is read into a buffer that it will process later. It can be moved back and forth in the buffer when needed, which increases the flexibility in the processing process. Use It provides a non-blocking, highly scalable network.
HTTP2.0 uses multiplexing technology to allow the same connection to process multiple requests concurrently, and the number of concurrent requests is several orders of magnitude larger than HTTP1.1.
In short, NIO can handle multiple requests with one thread.
Flow chart description:
channel is bidirectional and can return the status of the underlying operating system, such as Linux. The underlying operating system channel is bidirectional;
The buffer is essentially a memory block that can read and write data. It can be understood as a container object (including an array). This object provides a set of methods to make it easier to use the memory block. , The buffer object has some built-in mechanisms that can track and record the status changes of the buffer. Channel provides a channel for reading data from files and networks, but the data read or written must go through Buffer.
In NIO, Buffer is a top-level parent class, which is an abstract class.
ByteBuffer, stores byte data in the buffer;
ShortBuffer, stores string data into the buffer;
CharBuffer, stores character data into the buffer;
IntBuffer, stores integers Data to the buffer;
LongBuffer, stores long integer data into the buffer;
DoubleBuffer, stores decimals into the buffer;
FloatBuffer, stores decimals in the buffer;
## introduced when JDK1.4
##public final int capacity( )//Returns the capacity of this buffer9. Channel
1. Basic introduction (4) Commonly used Channel classes include: FileChannel, DatagramChannel, ServerSocketChannel and SocketChannel. ServerSocketChanne is similar to ServerSocket, and SocketChannel is similar to Socket.
(5) FileChannel is used for file data reading and writing, DatagramChannel is used for UDP data reading and writing, ServerSocketChannel and SocketChannel are used for TCP data reading and writing.
ByteBuffer supports typed put and get, put into What data type is, get should use the corresponding data type to retrieve, otherwise there may be a BufferUnderflowException exception.
You can convert a normal Buffer into a read-only Buffer.
NIO also provides MappedByteBuffer, which allows files to be modified directly in memory (memory outside the heap), and how to synchronize to files is completed by NIO.
NIO also supports reading and writing operations through multiple Buffers (i.e. Buffer arrays), namely Scattering and Gathering.
Java’s NIO , using non-blocking IO mode. You can use one thread to handle multiple client connections, and you will use the Selector.
Selector can detect whether an event occurs on multiple registered channels. If an event occurs, it obtains the event and handles each event accordingly. In this way, only a single thread can be used to manage multiple channels, that is, to manage multiple connections and requests.
Reading and writing will only occur when there are actual read and write events on the connection/channel, which greatly reduces system overhead and eliminates the need to create a thread for each connection. No need to maintain multiple threads.
Avoids the overhead caused by context switching between multiple threads.
package com.nezha.guor.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.util.Iterator;public class NioServer { private Selector selector; private ServerSocketChannel serverSocketChannel; private static final int PORT = 8080; public NioServer() { try { //获得选择器 selector = Selector.open(); serverSocketChannel = ServerSocketChannel.open(); //绑定端口 serverSocketChannel.socket().bind(new InetSocketAddress(PORT)); //设置非阻塞模式 serverSocketChannel.configureBlocking(false); //将该ServerSocketChannel 注册到selector serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); }catch (IOException e) { System.out.println("NioServer error:"+e.getMessage()); } } public void listen() { System.out.println("监听线程启动: " + Thread.currentThread().getName()); try { while (true) { int count = selector.select(); if(count > 0) { //遍历得到selectionKey集合 Iterator<selectionkey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); if(key.isAcceptable()) { SocketChannel sc = serverSocketChannel.accept(); sc.configureBlocking(false); sc.register(selector, SelectionKey.OP_READ); System.out.println(sc.getRemoteAddress() + " 上线 "); } //通道发送read事件,即通道是可读的状态 if(key.isReadable()) { getDataFromChannel(key); } //当前的key 删除,防止重复处理 iterator.remove(); } } else { System.out.println("等待中"); } } }catch (Exception e) { System.out.println("listen error:"+e.getMessage()); } } private void getDataFromChannel(SelectionKey key) { SocketChannel channel = null; try { channel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); int count = channel.read(buffer); //根据count的值做处理 if(count > 0) { String msg = new String(buffer.array()); System.out.println("来自客户端: " + msg); //向其它的客户端转发消息(排除自己) sendInfoToOtherClients(msg, channel); } }catch (IOException e) { try { System.out.println(channel.getRemoteAddress() + " 离线了"); //取消注册 key.cancel(); }catch (IOException ex) { System.out.println("getDataFromChannel error:"+ex.getMessage()); } }finally { try { channel.close(); }catch (IOException ex) { System.out.println("channel.close() error:"+ex.getMessage()); } } } //转发消息给其它客户(通道) private void sendInfoToOtherClients(String msg, SocketChannel self ) throws IOException{ System.out.println("服务器转发消息中..."); System.out.println("服务器转发数据给客户端线程: " + Thread.currentThread().getName()); //遍历 所有注册到selector 上的 SocketChannel,并排除 self for(SelectionKey key: selector.keys()) { Channel targetChannel = key.channel(); //排除自己 if(targetChannel instanceof SocketChannel && targetChannel != self) { SocketChannel dest = (SocketChannel)targetChannel; //将信息存储到buffer ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes()); //将buffer数据写入通道 dest.write(buffer); } } } public static void main(String[] args) { //创建服务器对象 NioServer nioServer = new NioServer(); nioServer.listen(); }}</selectionkey>
package com.nezha.guor.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.util.Iterator;import java.util.Scanner;public class NioClient { private final int PORT = 8080; //服务器端口 private Selector selector; private SocketChannel socketChannel; private String username; public NioClient() throws IOException { selector = Selector.open(); socketChannel = socketChannel.open(new InetSocketAddress("127.0.0.1", PORT)); //设置非阻塞 socketChannel.configureBlocking(false); //将channel注册到selector socketChannel.register(selector, SelectionKey.OP_READ); username = socketChannel.getLocalAddress().toString().substring(1); System.out.println(username + " is ok..."); } //向服务器发送消息 public void sendInfo(String info) { info = username + " 说:" + info; try { socketChannel.write(ByteBuffer.wrap(info.getBytes())); }catch (IOException e) { System.out.println("sendInfo error:"+e.getMessage()); } } //读取从服务器端回复的消息 public void readInfo() { try { int readChannels = selector.select(); if(readChannels > 0) { Iterator<selectionkey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = iterator.next(); if(key.isReadable()) { //得到相关的通道 SocketChannel sc = (SocketChannel) key.channel(); //得到一个Buffer ByteBuffer buffer = ByteBuffer.allocate(1024); //读取 sc.read(buffer); //把读到的缓冲区的数据转成字符串 String msg = new String(buffer.array()); System.out.println(msg.trim()); } } iterator.remove(); //删除当前的selectionKey, 防止重复操作 } else { System.out.println("没有可以用的通道..."); } }catch (Exception e) { System.out.println("readInfo error:"+e.getMessage()); } } public static void main(String[] args) throws Exception { NioClient nioClient = new NioClient(); new Thread() { public void run() { while (true) { nioClient.readInfo(); try { Thread.currentThread().sleep(2000); }catch (InterruptedException e) { System.out.println("sleep error:"+e.getMessage()); } } } }.start(); //发送数据给服务器端 Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()) { nioClient.sendInfo(scanner.nextLine()); } }}</selectionkey>
## Recommended study: "
The above is the detailed content of Take you to fully master Java NIO (summary sharing). For more information, please follow other related articles on the PHP Chinese website!