Netty 快速入门系列 - Chapter 1 传统OIO与NIO - NIO 【第二讲】

Chapter1 章节结构


NIO 特点                                 OIO 比较

ServerSocketChannel    -->  ServerSocket
SocketChannel              --> Socket
Selector (多路复用)

SelectionKey

特点:一个服务员服务多个客户,主要通过Selector多路服务


代码:


package com.john.netty.learn.ch01.nio;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;


public class NioServer {


  private Selector selector = null;


  private int port;


  public NioServer(int port) throws IOException {


    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();


    // 不堵塞
    serverSocketChannel.configureBlocking(false);


    serverSocketChannel.socket().bind(new InetSocketAddress(port));


    selector = Selector.open();


    // 注册我感兴趣的事件, 这里 Accept 新的客户接入
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);


    this.port = port;
  }


  public void listen() throws IOException {


    System.out.println("启动服务" + port);


    while (true) {


      selector.select();


      Iterator<SelectionKey> it = selector.selectedKeys().iterator();


      while (it.hasNext()) {


        SelectionKey selectionKey = it.next();


        // 避免重复
        it.remove();


        handler(selectionKey);


      }


    }


  }


  private void handler(SelectionKey selectionKey) throws IOException {

    //当触发Socket.accpet 事件时,即有新的客户连接
    if (selectionKey.isAcceptable()) {
      // Key 包含 serverSocketChannel
      // Refer to serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
      handlerAccept(selectionKey);


      return;
    }


    if (selectionKey.isReadable()) {


      handlerRead(selectionKey);
    }


  }


  private void handlerRead(SelectionKey selectionKey) throws IOException {


    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();


    ByteBuffer buffer = ByteBuffer.allocate(1024);


    socketChannel.read(buffer);


    System.out.println("接收到消息:" + new String(buffer.array()));


    buffer.flip();


    socketChannel.write(buffer);


  }


  private void handlerAccept(SelectionKey selectionKey) throws IOException {


    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();


    // 获取新的客户端-与新客户端握手
    SocketChannel socketChannel = serverSocketChannel.accept();


    socketChannel.configureBlocking(false);


    System.out.println("一个新客户连入...");


    // 注册SocketChannel 读的感兴趣
    socketChannel.register(this.selector, SelectionKey.OP_READ);
  }


  public static void main(String[] args) throws IOException {


    NioServer nioServer = new NioServer(2000);


    nioServer.listen();
  }


}

 

问题解答:

1. Selector.select();阻塞,那为什么说NIO是非阻塞的IO?
  a. 一个Socket系统对于阻塞和非阻塞,主要关心的不是在Accept 、Select 上, 而是在 read socket 流的时候,是否堵塞。
  b. selector.select(1000);不阻塞
     selector.wakeup();也可以唤醒selector (select方法) -- 这个非常重要,再随后的Netty源码中将讲解
     selector.selectNow();也可以立马返还

2、客户端关闭的时候会抛出异常,死循环

3、SelectionKey.OP_WRITE是代表什么意思?
   OP_WRITE表示底层缓冲区是否有空间,是则响应返还true

所有源码下载 :https://download.csdn.net/download/netcobol/10308871
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值