【Java nio】 NonBlocking NIO

  1 package com.slp.nio;
  2 
  3 import org.junit.Test;
  4 
  5 import java.io.IOException;
  6 import java.net.InetSocketAddress;
  7 import java.nio.ByteBuffer;
  8 import java.nio.channels.SelectionKey;
  9 import java.nio.channels.Selector;
 10 import java.nio.channels.ServerSocketChannel;
 11 import java.nio.channels.SocketChannel;
 12 import java.time.LocalDateTime;
 13 import java.util.Date;
 14 import java.util.Iterator;
 15 import java.util.Scanner;
 16 
 17 /**
 18  * Created by sanglp on 2017/3/2.
 19  * 一、使用NIO完成网络通信的三个核心
 20  * 1、通道:负责连接
 21  *     |--java.nio.channels.channel接口
 22  *        |--SelectableChannel
 23  *           |--SocketChannel
 24  *           |--ServerSocketChannel
 25  *           |--DatagramChannel
 26  *
 27  *           |--Pipe.SinkChannel
 28  *           |--Pipe.SourceChannel
 29  * 2、缓冲区:负责数据的存取
 30  * 3、选择器:是SelectableChannel的多路复用器,用于监控SelectableChannel的IO状况
 31  *
 32  */
 33 public class TestNonBlockingNIO {
 34 
 35     @Test
 36     public void client() throws IOException {
 37         //获取通道
 38         SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1",9898));
 39         //切换为非阻塞模式
 40       socketChannel.configureBlocking(false);
 41         //分配缓冲区
 42         ByteBuffer buf = ByteBuffer.allocate(1024);
 43         //发送数据给服务端
 44 
 45         Scanner scanner = new Scanner(System.in);
 46         while (scanner.hasNext()){
 47             String str = scanner.next();
 48             buf.put((new Date().toString()+"
"+str).getBytes());
 49             buf.flip();
 50             socketChannel.write(buf);
 51             buf.clear();
 52         }
 53 
 54 
 55         //关闭通道
 56         socketChannel.close();
 57 
 58     }
 59 
 60     @Test
 61     public void server() throws IOException {
 62         //获取通道
 63        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
 64         //切换非阻塞模式
 65         serverSocketChannel.configureBlocking(false);
 66         //绑定连接
 67         serverSocketChannel.bind(new InetSocketAddress(9898));
 68         //获取一个选择器
 69         Selector selector = Selector.open();
 70         //将通道注册到选择器上 并且指定监听接收事件
 71         serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
 72         //轮询式的获取选择器上已经准备就绪的事件
 73         while (selector.select()>0){
 74             //获取当前选择器中所有注册的选择键(已就绪的监听事件)
 75             Iterator<SelectionKey> it = selector.selectedKeys().iterator();
 76             while (it.hasNext()){
 77                 //获取准备就绪的事件
 78                 SelectionKey sk = it.next();
 79                 //判断具体是什么事件准备就绪
 80                 if(sk.isAcceptable()){
 81                     //获取额护短连接
 82                     SocketChannel socketChannel = serverSocketChannel.accept();
 83                     //切换非阻塞模式
 84                     socketChannel.configureBlocking(false);
 85                     //将该通道注册到选择器上
 86                     socketChannel.register(selector,SelectionKey.OP_READ);
 87                 }else if(sk.isReadable()){
 88                     //获取当前选择器上读就绪状态的通道
 89                     SocketChannel socketChannel = (SocketChannel) sk.channel();
 90                     //读取数据
 91                     ByteBuffer buffer = ByteBuffer.allocate(1024);
 92                     int len =0;
 93                     while ((len=socketChannel.read(buffer))>0){
 94                         buffer.flip();
 95                         System.out.println(new String(buffer.array(),0,len));
 96                         buffer.clear();
 97                     }
 98                 }
 99                 //取消选择键
100                 it.remove();
101             }
102         }
103     }
104 }
原文地址:https://www.cnblogs.com/dream-to-pku/p/6505539.html