IO与NIO阻塞分析以及nio实现

一、概念(io\nio)

    Java nio是一个基于缓冲区、并能提供非阻塞I/O操作的Java API,因此nio也被看成是non-blocking I/O的缩写。它拥有比传统I/O操作(bio)更好的并发运行性能。。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。IO是面向流的,NIO是面向缓冲区的。

nio特性:

1 为所有原始类型提供给缓存支持

2 提供一个新的管道 chanel

3 支持锁和内存映射文件的访问接口

4 多路复用(linux就是用的这个模型)

二 、阻塞与非阻塞

阻塞:传统io的各种流都是阻塞的。

阻塞点:1 Socket等待客户端连接

               2 读取流中数据

这样线程就会被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。开启多线程的话,为每一个请求开启一个线程,这种方法如果流量多,那么就浪费系统资源。

非阻塞:也是有组赛点的     this.selector.select();,但是读写数据的时候是没有阻塞点的。

阻塞io基于socket的嘛,我们就先不说,下面是nio的简单实现,代码如下:


public class ServerNIO {
    
    private Selector selector;//注册选择器
    private String uri;
    private String agreement;//协议
    public static void main(String[] args) {
        ServerNIO server= new ServerNIO();
        try {
            server.initServer(7001);
            server.ListenSelector();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
    public void initServer(int port) throws Exception {
        //服务端开启
        ServerSocketChannel  serverChannel = ServerSocketChannel.open();
        //阻塞改为false
        serverChannel.configureBlocking(false);
        //绑定端口
        serverChannel.socket().bind(new InetSocketAddress(port));
        
        this.selector = Selector.open();
        //为选择器注册监听事件
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务端已开启。。。");
    }
    
    public void ListenSelector() throws Exception{
        //轮询监听selector
        while(true) {
            this.selector.select();
            Iterator<SelectionKey> iterator = this.selector.selectedKeys().iterator();
            if(iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                //有效key
                if(selectionKey.isValid()) {
                    //处理当前请求
                    handler(selectionKey);
                }
                
            }
        }
    }
    /**  
    
     * <p>处理客户端请求</p>  
     * @param selectionKey  
     * @throws IOException 
    
     */ 
    private void handler(SelectionKey key) throws IOException {
        //判断是什么类型的请求    连接请求
        if(key.isAcceptable()) {
            ServerSocketChannel  serverChannel = (ServerSocketChannel)key.channel();
            SocketChannel  socketChannel = serverChannel.accept();
            socketChannel.configureBlocking(false);
            //设置读超时
            socketChannel.socket().setSoTimeout(5000);
            //如果接收到连接请求后,需要给请求注册读权限
            socketChannel.register(selector, SelectionKey.OP_READ);
        }
        //读请求
        if(key.isReadable()) {
            SocketChannel  socketChannel = (SocketChannel)key.channel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            if((socketChannel.read(buffer))>0) {
                String msg = new String(buffer.array());
                HttpRequestNIO request= new HttpRequestNIO(msg);
                uri = request.getUri();
                agreement = request.getAgreement().trim();
                if(isStatic(uri)) {
                    socketChannel.register(selector, SelectionKey.OP_WRITE);
                    System.out.println("此处返回静态文件");
                }else {
                    System.out.println("此处返回动态文件");
                }
            }else {
                System.out.println("客户端关闭");
                key.cancel();
                return;
            }
        }
        if(key.isWritable()) {
            SocketChannel  socketChannel = (SocketChannel)key.channel();
            HttpResponseNIO Response = new HttpResponseNIO(socketChannel);
            Response.wirte(uri);
            Response.wirteAgreement(agreement);
        }
        
    }
    private static Boolean isStatic(String uri) {
        Boolean isStatic = false;
        String[] suffix = {".html",".css",".png",".jpeg",".js",".ico"};
        for (String string : suffix) {
            if(uri.endsWith(string)) {
                isStatic = true;
            }
        }
        return isStatic;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值