NIO 简单实现

1.先看官方解释

Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。

Java NIO: Channels and Buffers(通道和缓冲区)

标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。

Java NIO: Non-blocking IO(非阻塞IO)

Java NIO可以让你非阻塞的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。

Java NIO: Selectors(选择器)

Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。

2.自己简单理解

首先它改善了我们传统阻塞io的缺点,使用一个叫多路复用器(selector)的纽带,通过socketchannel与serversocketchannel 通道进行通信,这样就使得我们通过单线程(selector )来分发处理多客户端请求,减少资源占有,同时提供了异步处理方式提高效率。理解图如下,

简单代码:

package com.cai.nioservice;

import java.io.IOException;
import java.net.InetSocketAddress;
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 NioService {
    //声明全局的多路复用器
    private Selector selector;
    //初始化服务器端信息
    public void initNioServer() throws Exception {
        //创建服务通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //设置异步
        serverSocketChannel.configureBlocking(false);
        //绑定一个通道
        serverSocketChannel.socket().bind(new InetSocketAddress(8000));
        //使用多路复用器接受客户端请求
        this.selector=selector.open();
        //使用多路复用器与socketchannel创建联系
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);//注册接受状态
    }
    /**
     * 复写监听事件
     * @throws Exception 
     */
    public void listen() throws Exception {
        System.err.println("服务器端启动。。。。。。");
        //使用for循环处理监听到的socketchannel 状态
        while(true) {
            //获取多路复用器中注册的socketchannel事件状态
            //当注册的事件到达时,方法返回;否则,该方法会一直阻塞
            selector.select();
            Iterator<SelectionKey> keys= this.selector.selectedKeys().iterator();
            while(keys.hasNext()) {
                SelectionKey key=keys.next();//获取数据交换 的通道标识
                //首先移除之前处理过的key,防止事件重复处理
                keys.remove();
                handle(key);
            }            
        }
    }
    //处理监听到的事件
    public void handle(SelectionKey key) throws Exception {
        //判断监听状态
        if(key.isAcceptable()) {
            handleAccept(key);
        }else if(key.isConnectable()) {
            handleConnect(key);
        }else if(key.isReadable()) {
            handleRead(key);
        }
    }
    private void handleRead(SelectionKey key) throws Exception {
        SocketChannel socketChannel = (SocketChannel)key.channel();    
        //创建读取缓冲区大小
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int read = socketChannel.read(buffer);
        if(read > 0) {
            byte[] bytes =buffer.array();
            String s = new String(bytes);
            System.err.println("接受消息为 : " + s);
            ByteBuffer outBuffer = ByteBuffer.wrap("接受到了啊".getBytes());
            socketChannel.write(outBuffer);// 将消息回送给客户端
        }else {
            System.err.println("关闭链接");
            key.cancel();
        }
    }
    private void handleConnect(SelectionKey key) {
        System.err.println("链接成功!");
        
    }
    private void handleAccept(SelectionKey key) throws Exception {
        //客户端请求
        //通过key获取与客户端对接的通道
        ServerSocketChannel server = (ServerSocketChannel)key.channel();
        //通过服务端通道获取与客户端对用channel
        SocketChannel socketChannel = server.accept();
        //设置非阻塞
        socketChannel.configureBlocking(false);
        //改变通道状态,由接受改为可处理读取状态
        socketChannel.register(selector, SelectionKey.OP_READ);
    }
    public static void main(String[] args) throws Exception {
        NioService service = new NioService();
        service.initNioServer();
        service.listen();
    }
    
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值