NIO教程(3)

简介: NIO教程

NIO教程(2)https://developer.aliyun.com/article/1530796

服务端流程

  • 1、当客户端连接服务端时,服务端会通过 ServerSocketChannel 得到 SocketChannel:1. 获取通道
ServerSocketChannel ssChannel = ServerSocketChannel.open();
  • 2、切换非阻塞模式
ssChannel.configureBlocking(false);
  • 3、绑定连接
ssChannel.bind(new InetSocketAddress(9999));
  • 4、 获取选择器
Selector selector = Selector.open();
  • 5、 将通道注册到选择器上, 并且指定“监听接收事件”
ssChannel.register(selector, SelectionKey.OP_ACCEPT);
  1. 轮询式的获取选择器上已经“准备就绪”的事件
//轮询式的获取选择器上已经“准备就绪”的事件
   while (selector.select() > 0) {
          System.out.println("轮一轮");
          //7. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)”
          Iterator<SelectionKey> it = selector.selectedKeys().iterator();
          while (it.hasNext()) {
              //8. 获取准备“就绪”的是事件
              SelectionKey sk = it.next();
              //9. 判断具体是什么事件准备就绪
              if (sk.isAcceptable()) {
                  //10. 若“接收就绪”,获取客户端连接
                  SocketChannel sChannel = ssChannel.accept();
                  //11. 切换非阻塞模式
                  sChannel.configureBlocking(false);
                  //12. 将该通道注册到选择器上
                  sChannel.register(selector, SelectionKey.OP_READ);
              } else if (sk.isReadable()) {
                  //13. 获取当前选择器上“读就绪”状态的通道
                  SocketChannel sChannel = (SocketChannel) sk.channel();
                  //14. 读取数据
                  ByteBuffer buf = ByteBuffer.allocate(1024);
                  int len = 0;
                  while ((len = sChannel.read(buf)) > 0) {
                      buf.flip();
                      System.out.println(new String(buf.array(), 0, len));
                      buf.clear();
                  }
              }
              //15. 取消选择键 SelectionKey
              it.remove();
          }
      }
  }

客户端流程

  1. 获取通道
SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9999));
  1. 切换非阻塞模式
sChannel.configureBlocking(false);
  1. 分配指定大小的缓冲区
ByteBuffer buf = ByteBuffer.allocate(1024);
  1. 发送数据给服务端
Scanner scan = new Scanner(System.in);
    while(scan.hasNext()){
      String str = scan.nextLine();
      buf.put((new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(System.currentTimeMillis())
          + "\n" + str).getBytes());
      buf.flip();
      sChannel.write(buf);
      buf.clear();
    }
    //关闭通道
    sChannel.close();

4.8 NIO非阻塞式网络通信入门案例

需求:服务端接收客户端的连接请求,并接收多个客户端发送过来的事件。

代码案例

/**
  客户端
 */
public class Client {
  public static void main(String[] args) throws Exception {
    //1. 获取通道
    SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9999));
    //2. 切换非阻塞模式
    sChannel.configureBlocking(false);
    //3. 分配指定大小的缓冲区
    ByteBuffer buf = ByteBuffer.allocate(1024);
    //4. 发送数据给服务端
    Scanner scan = new Scanner(System.in);
    while(scan.hasNext()){
      String str = scan.nextLine();
      buf.put((new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(System.currentTimeMillis())
          + "\n" + str).getBytes());
      buf.flip();
      sChannel.write(buf);
      buf.clear();
    }
    //5. 关闭通道
    sChannel.close();
  }
}
/**
 服务端
 */
public class Server {
    public static void main(String[] args) throws IOException {
        //1. 获取通道
        ServerSocketChannel ssChannel = ServerSocketChannel.open();
        //2. 切换非阻塞模式
        ssChannel.configureBlocking(false);
        //3. 绑定连接
        ssChannel.bind(new InetSocketAddress(9999));
        //4. 获取选择器
        Selector selector = Selector.open();
        //5. 将通道注册到选择器上, 并且指定“监听接收事件”
        ssChannel.register(selector, SelectionKey.OP_ACCEPT);
        //6. 轮询式的获取选择器上已经“准备就绪”的事件
        while (selector.select() > 0) {
            System.out.println("轮一轮");
            //7. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)”
            Iterator<SelectionKey> it = selector.selectedKeys().iterator();
            while (it.hasNext()) {
                //8. 获取准备“就绪”的是事件
                SelectionKey sk = it.next();
                //9. 判断具体是什么事件准备就绪
                if (sk.isAcceptable()) {
                    //10. 若“接收就绪”,获取客户端连接
                    SocketChannel sChannel = ssChannel.accept();
                    //11. 切换非阻塞模式
                    sChannel.configureBlocking(false);
                    //12. 将该通道注册到选择器上
                    sChannel.register(selector, SelectionKey.OP_READ);
                } else if (sk.isReadable()) {
                    //13. 获取当前选择器上“读就绪”状态的通道
                    SocketChannel sChannel = (SocketChannel) sk.channel();
                    //14. 读取数据
                    ByteBuffer buf = ByteBuffer.allocate(1024);
                    int len = 0;
                    while ((len = sChannel.read(buf)) > 0) {
                        buf.flip();
                        System.out.println(new String(buf.array(), 0, len));
                        buf.clear();
                    }
                }
                //15. 取消选择键 SelectionKey
                it.remove();
            }
        }
    }
}

NIO教程(4)https://developer.aliyun.com/article/1530800

相关文章
|
6月前
|
存储 弹性计算 监控
|
6月前
|
缓存 Java 索引
|
6月前
|
Java API
|
Java
Java NIO系列教程三
​ 今天主要给大家介绍的是Buffer的基本使用这个也是NIO里面最总要的概率之一,里面的操作也是有一些复杂的同时也是需要大家必须要重点掌握的知识点,同时也介绍了一下Selector的用法下一篇文章我们将为大家介绍Pipe管道以及FileLock文件锁这也是NIO里面最后的一分部内容了。
103 0
|
安全 Java API
Java NIO系列教程四【完】-管道-文件锁-异步写入
​ 到此位置NIO的所有的内容都结束了,对于NIO来说主要是各种概念需要大家去理解然后有很多的用法和api也需要大家去熟悉所以想把NIO学懂学好其实并不容易一定要多写案例去测试巩固,也预祝大家能把NIO的知识看懂理顺!!!
103 0
|
网络协议 Java
Java NIO系列教程一
今天主要给大家介绍的是NIO的基本的概念以及Channel中常用的FileChannel的基本的用法,算是对Channel有一个简单的介绍。下一篇文章我们将详细的为大家介绍其他的常用Channel。
125 0
Java NIO系列教程一
|
网络协议 Java
Java NIO系列教程二
​ 今天主要是为大家详细的介绍了常见的各种Channel以及他们的用法,本文编写了大量的案例还需要大家认真的去实践以后才能真正的掌握住。介绍完Channel那么下一篇文章我们就可以为大家介绍Buffer和Selector的具体使用了。
90 0
|
Java
Java NIO系列教程(8)-SocketChannel的最佳实践(下)
Java NIO系列教程(8)-SocketChannel的最佳实践
188 0
|
网络协议 Java
Java NIO系列教程(8)-SocketChannel的最佳实践(上)
Java NIO系列教程(8)-SocketChannel的最佳实践
459 0
|
监控 Java
Java NIO系列教程(六) Selector
Java NIO系列教程(六) Selector
138 0