Channel
IO Operations Link, where a Channel represents an open connection to an entity. In network IO, it is usually used to read/write data with Buffer.
Implementations of some of the major Channel s in JAVA NIO
- FileChannel: Read and write data from a file.
- DatagramChannel: Can read and write data in the network through UDP.
- SocketChannel: Can read and write data in the network over TCP.
- ServerSocketChannel: Can listen for new incoming TCP connections like Web servers. A SocketChannel is created for each new connection.
common method
- int read(ByteBuffer var1) read bytes from Buffer
- int write(ByteBuffer src) writes data to Buffer
- boolean connect(SocketAddress remote) client connects to an address
- SocketChannel accept() accepts connections and creates SocketChannel
Buffer
Buffer is essentially a piece of memory that can write data and then read it. This block of memory is packaged as a NIO Buffer object and provides a set of methods for accessing it easily.
Key Buffer implementations in Java NIO
These implementations basically cover the basic data types for all IO transmissions
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
common method
- ByteBuffer allocate(int capacity): Create a buffer of a specified size
- ByteBuffer put(byte b): Writes the specified byte to the buffer, and read for the channel writes the channel's data to the buffer
- byte get(): read data from buffer, write of channel writes data from buffer to channel
- Buffer flip() read-write mode switch
Selector
Selector (Multiplexer). It is one of the core components of Java NIO and listens on multiple Channels at the same time. When a particular event occurs on a channel, these channels become available.
common method
- public static Selector open(): Create selector
- The final SelectionKey register(Selector sel, int ops) method is channel, the selector is passed in as a parameter, and the second parameter is in, an event. When a channel triggers an event, it becomes ready. These four events are
- SelectionKey.OP_READ:: Read events for both ends
- SelectionKey.OP_WRITE:: Write time, for both ends
- SelectionKey.OP_CONNECT:: Connection Completion Event (TCP Connection), applicable only to clients
- SelectionKey.OP_ACCEPT:: Accept new connection events, only for server side
- Set selectedKeys(): Returns the corresponding SelectionKeys
- int select(): blocked to a channel ready, how many channels are returned ready
- int select(long timeout): increase timeout mechanism
- public abstract int selectNow(): Returns the quantity immediately without blocking.
SelectionKey
SelectionKey represents a token registered by a channel to a selector
common method
- SelectionKey interestOps(): Returns a collection of events of interest
- Object attach(Object ob): Add an attachment to the SelectionKey
- Object attachment(): Take the attachment out of SelectionKey
SocketChannel
SocketChannel is the channel that connects to a TCP network socket.
Created as SocketChannel.open or ServerSocketChannel.accept(), described above, repeated below
ServerSocketChannel
ServerSocketChannel is the channel that listens for new incoming TCP connections
Traditional IO Programming [Simplified Version]
Now that you know these basic concepts, let's start with the Network Programming section, which starts with a simple example.
Server
public class NIOServer { public static void main(String[] args) throws IOException { //Create ServerSocketChannel to handle access connections ServerSocketChannel serverSocketChannel=ServerSocketChannel.open(); //Set whether to be non-blocking serverSocketChannel.configureBlocking(false); //Binding Port Number serverSocketChannel.socket().bind(new InetSocketAddress(8080)); while (true){ if(serverSocketChannel.isOpen()){ SocketChannel socketChannel=serverSocketChannel.accept(); if(socketChannel!=null){ //Read data ByteBuffer buffer = ByteBuffer.allocate(1024); int bytesRead = socketChannel.read(buffer); buffer.flip(); byte[] bytes = new byte[buffer.remaining()]; System.arraycopy(buffer.array(), buffer.position(), bytes, 0, buffer.remaining()); System.out.println(new String(bytes, "UTF-8")); //Channel closure socketChannel.close(); } } } } }
Client
public static void main(String[] args) throws IOException, InterruptedException { for (int i = 0; i < 30; i++) { SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress(8080)); if(socketChannel.isConnected()){ ByteBuffer buffer=ByteBuffer.allocate(1024); buffer.put("hello world".getBytes()); System.out.println("hello world"); buffer.flip(); while(buffer.hasRemaining()) { socketChannel.write(buffer); } socketChannel.close(); } } }
Is simply sending data
Then the problem comes. It's a simple network programming, but there are still many problems. For example, the server can only process new connections and the first received information, but it can't process subsequent sent data. There are still many problems. Here we use Selector, optimized for this example
Traditional IO programming
Server
public class NIOServer2 { public static void main(String[] args) throws IOException { //Create ServerSocketChannel to handle access connections ServerSocketChannel serverSocketChannel=ServerSocketChannel.open(); //Create Selector Selector selector=Selector.open(); //Set whether to be non-blocking serverSocketChannel.configureBlocking(false); //Create registered channel s into selector creation connection time serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); //Binding Port Number serverSocketChannel.socket().bind(new InetSocketAddress(8080)); while (true){ if(serverSocketChannel.isOpen()){ // Select Channel through Selector int selectNums = selector.select(1000L); if (selectNums == 0) { continue; } // Traverse the SelectionKey collection of selectable Channel s for (SelectionKey selectKey:selector.selectedKeys()) { // Ignore invalid SelectionKey if (!selectKey.isValid()) { continue; } //New Connection Created if(selectKey.isAcceptable()){ //Get the channel created by the new connection SocketChannel socketChannel= ((ServerSocketChannel) selectKey.channel()).accept(); if(socketChannel!=null){ //Set to non-blocking socketChannel.configureBlocking(false); //Register with selector socketChannel.register(selector,SelectionKey.OP_READ); } } //Processing Read Time if(selectKey.isReadable()){ SocketChannel socketChannel= (SocketChannel) selectKey.channel(); if(socketChannel!=null){ //Read data ByteBuffer buffer = ByteBuffer.allocate(1024); int bytesRead = socketChannel.read(buffer); if(bytesRead==-1){ socketChannel.register(selector,0); socketChannel.close(); }else{ buffer.flip(); byte[] bytes = new byte[buffer.remaining()]; System.arraycopy(buffer.array(), buffer.position(), bytes, 0, buffer.remaining()); System.out.println(new String(bytes, "UTF-8")); } } } } } } } }
Client
public static void main(String[] args) throws IOException, InterruptedException { SocketChannel socketChannel = SocketChannel.open(); socketChannel.connect(new InetSocketAddress(8080)); for (int i = 0; i < 30; i++) { if(socketChannel.isConnected()){ ByteBuffer buffer=ByteBuffer.allocate(1024); buffer.put("hello world".getBytes()); System.out.println("hello world"); buffer.flip(); while(buffer.hasRemaining()) { socketChannel.write(buffer); } } } socketChannel.close(); }
It is now possible to handle different events differently
Reference Article
http://ifeve.com/java-nio-all/