• Netty——NIO(Selector处理accept事件)代码示例


    一、服务端代码示例

    • 服务端代码示例

      package com.example.nettytest.nio.day3;
      
      import lombok.extern.slf4j.Slf4j;
      import java.io.IOException;
      import java.net.InetSocketAddress;
      import java.nio.channels.SelectionKey;
      import java.nio.channels.Selector;
      import java.nio.channels.ServerSocketChannel;
      import java.nio.channels.SocketChannel;
      import java.util.Iterator;
      import java.util.Set;
      
      /**
       * @description: Selector处理accept事件 代码示例
       * @author: xz
       * @create: 2022-09-01
       */
      @Slf4j
      public class Test2Server {
          public static void main(String[] args) {
              nioSelectorAcceptServer();
          }
          /**
           * Selector处理accept事件 方法
           * */
          private static void nioSelectorAcceptServer(){
              try (ServerSocketChannel channel = ServerSocketChannel.open()) {//1、创建服务器
                  //绑定监听端口
                  channel.bind(new InetSocketAddress(8080));
                  //设置为非阻塞模式
                  channel.configureBlocking(false);
                  System.out.println("channel=="+channel);
      
                  /**
                   * 2、创建Selector,管理多个channel
                   */
                  Selector selector = Selector.open();
                  /**
                   * 3、建立Selector与channel的联系(也称为注册)
                   * key只关注事件,绑定的事件类型4种,connect - 客户端连接成功时触发;accept - 服务器端成功接受连接时触发; read - 数据可读入时触发;write - 数据可写出时触发,
                   * */
                  channel.register(selector, SelectionKey.OP_ACCEPT);
      
                  while(true){
                      /**
                       * 3、select 方法, 没有事件发生,线程阻塞,有事件,线程才会恢复运行
                       *   select 在事件未处理时,它不会阻塞
                       */
                      int count = selector.select();
                      log.debug("select count: {}", count);
                      // 获取所有事件
                      Set<SelectionKey> keys = selector.selectedKeys();
                      // 遍历所有事件,逐一处理
                      Iterator<SelectionKey> iterator = keys.iterator();
                      //遍历所有事件,逐一处理
                      while(iterator.hasNext()){
                          SelectionKey key = iterator.next();
                          log.info("key===={}",key);
                          // 判断事件类型,如果事件类型是 accept - 服务器端成功接受连接时触发;
                          if (key.isAcceptable()) {
                              //channel中有哪些key
                              ServerSocketChannel c = (ServerSocketChannel) key.channel();
                              //必须处理 selector 上的 channel
                              SocketChannel sc = c.accept();
                              log.debug("sc==={}", sc);
                          }
                          // 处理完毕,必须将事件移除
                          iterator.remove();
                      }
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75

    二、客户端代码示例

    • 客户端代码示例

      package com.example.nettytest.nio.day3;
      
      import java.io.IOException;
      import java.net.Socket;
      /**
       * @description:
       * @author: xz
       * @create: 2022-09-01
       */
      public class Test2Client {
          public static void main(String[] args) {
              try (Socket socket = new Socket("localhost", 8080)) {
                  System.out.println(socket);
                  socket.getOutputStream().write("hello world".getBytes());
                  System.in.read();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20

    三、启动一个客户端测试

    • 先启动服务端
      由下图输出结果可知,由于没有事件发生,再select 方法处,线程阻塞。
      在这里插入图片描述

    • 再启动客户端
      在这里插入图片描述

    • 再查看服务端控制台输出
      由下图输出结果可知,由于有事件发生,再select 方法处,线程会恢复运行。
      在这里插入图片描述

    四、启动2个客户端测试

    • 再启动一个客户端
      在这里插入图片描述 - 再次查看服务端控制台输出
      由下图输出结果可知,由于有事件发生,再select 方法处,线程再次恢复运行。并且服务端2次接受的key是同一个对象。
      在这里插入图片描述

    五、事件发生后能否不处理

    • 事件发生后,要么处理,要么取消(cancel),不能什么都不做,否则下次该事件仍会触发,这是因为 nio 底层使用的是水平触发。
  • 相关阅读:
    【深入浅出Spring原理及实战】「夯实基础系列」360全方位渗透和探究Spring配置开发实战详解
    【TCP】滑动窗口、流量控制 以及拥塞控制
    only id(String) method calls allowed in plugins {} script block
    python科研绘图:帕累托图(Pareto chart)
    【C++】内存管理
    FTP无法在资源管理器中打开
    WebView2 通过 PuppeteerSharp 实现爬取 王者 壁纸 (案例版)
    UE5主视口导航快捷键汇总
    Flutter 笔记 | Flutter 事件与通知
    【UVM入门 ===> Episode_9 】~ 寄存器模型、寄存器模型的集成、寄存器模型的常规方法、寄存器模型的应用场景
  • 原文地址:https://blog.csdn.net/li1325169021/article/details/126652439