I. three cores of using Java NIO to complete network communication
1. Channel: responsible for connection
java.nio.channels.Channel interface:
|--SelectableChannel
|--SocketChannel
|--ServerSocketChannel
|--DatagramChannel
|--Pipe.SinkChannel
|--Pipe.SourceChannel
2. buffer: responsible for data access
3. Selector: it is the multiplexer of the selectable channel, which is used to detect the IO status of the selectable channel
Case: using non blocking to realize simple group chat system
I. implementation of client
1 public static void main(String[] args) throws Exception { 2 SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8989)); 3 4 //2. Switch non blocking mode 5 sChannel.configureBlocking(false); 6 7 //3. Allocate buffer of specified size 8 ByteBuffer buf = ByteBuffer.allocate(1024); 9 10 //4. Send data to the server 11 Scanner scan = new Scanner(System.in); 12 13 while (scan.hasNext()) { 14 String str = scan.next(); 15 buf.put((new Date().toString() + "\n" + str).getBytes()); 16 buf.flip(); 17 sChannel.write(buf); 18 buf.clear(); 19 } 20 21 //5. Close channel 22 sChannel.close(); 23 }
2. Realize the server
@Test public void server() { ServerSocketChannel ssChannel = null; try { ssChannel = ServerSocketChannel.open(); //Configure non blocking ssChannel.configureBlocking(false); //Binding connection ssChannel.bind(new InetSocketAddress(8989)); Selector selector = Selector.open(); //Register the channel to the listener, and set the listener's listening mode as "accept" ssChannel.register(selector, SelectionKey.OP_ACCEPT); //Events for which polling selection is ready while (selector.select() > 0) { //Get current listening Iterator<SelectionKey> it = selector.selectedKeys().iterator(); while (it.hasNext()) { //Get ready events SelectionKey sk = it.next(); if (sk.isAcceptable()) { //If ready to accept, get the client's connection SocketChannel clientChannel = ssChannel.accept(); //Also configured as non blocking clientChannel.configureBlocking(false); //Register the client's connection to the selector clientChannel.register(selector, SelectionKey.OP_READ); } else if (sk.isReadable()) { //If the read is ready, get the read channel SocketChannel socketChannel = (SocketChannel) sk.channel(); //Configure to non blocking mode socketChannel.configureBlocking(false); //Read data ByteBuffer byteBuffer = ByteBuffer.allocate(1024); int len = 0; while ((len = socketChannel.read(byteBuffer)) > 0) { byteBuffer.flip(); System.out.println(new String(byteBuffer.array(), 0, len)); byteBuffer.clear(); } } it.remove(); } } } catch (IOException e) { e.printStackTrace(); } finally { if(ssChannel!=null){ try { ssChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Note: here is the org.junit.Test used by the server. This package is convenient for testing. Because the client needs to read the input, it is written in the Main function (@ Test method seems unable to read the input)
The address to download the package is as follows:
Link: https://pan.baidu.com/s/14zhhonad3ldnvcaa3pmcojq
Extraction code: uqd9
How to use datagram channel (UDP) (similar to the previous case)
public static void main(String args[]) { DatagramChannel datagramChannel = null; try { datagramChannel = DatagramChannel.open(); datagramChannel.configureBlocking(false); ByteBuffer byteBuffer = ByteBuffer.allocate(1024); Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { String str = scanner.next(); byteBuffer.put(str.getBytes()); byteBuffer.flip(); datagramChannel.send(byteBuffer, new InetSocketAddress("127.0.0.1", 9897)); byteBuffer.clear(); } } catch (IOException e) { e.printStackTrace(); } finally { if(datagramChannel!=null){ try { datagramChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void server(){ DatagramChannel datagramChannel = null; try { datagramChannel=DatagramChannel.open(); datagramChannel.bind(new InetSocketAddress(9897)); datagramChannel.configureBlocking(false); Selector selector = Selector.open(); datagramChannel.register(selector, SelectionKey.OP_READ); while(selector.select()>0){ Iterator<SelectionKey> st=selector.selectedKeys().iterator(); while(st.hasNext()){ SelectionKey sk=st.next(); if(sk.isReadable()){ ByteBuffer btf=ByteBuffer.allocate(1024); datagramChannel.receive(btf); btf.flip(); System.out.println(new String(btf.array(),0,btf.limit())); btf.clear(); } } st.remove(); } } catch (IOException e) { e.printStackTrace(); } finally { if(datagramChannel!=null){ try { datagramChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Pipe introduction
Pipe is a single data connection between two threads. Pipe has two data channels. The Sign channel is responsible for writing and the Source channel is responsible for reading.
The cases are as follows:
@Test public void test() throws Exception { Pipe pipe = Pipe.open(); ByteBuffer byteBuffer = ByteBuffer.allocate(1024); byteBuffer.put("hello world".getBytes()); Pipe.SinkChannel sinkChannel=pipe.sink(); byteBuffer.flip(); sinkChannel.write(byteBuffer); //read Pipe.SourceChannel sourceChannel =pipe.source(); byteBuffer.flip(); int len=sourceChannel.read(byteBuffer); System.out.println("sourceChanel:"+new String(byteBuffer.array(),0,len)); byteBuffer.clear(); sinkChannel.close(); sourceChannel.close(); }
Thank you for browsing. If you have any questions, I will change my mistakes in time.