java.nio

1,什么是nio?

新的输入/输出 (NIO) 库是在 JDK 1.4 中引入的。NIO 弥补了原来的 I/O 的不足,它在标准 Java 代码中提供了高速的、面向块的 I/O。


2,nio的核心概念

    通道Channel

    通道channel是nio的核心概念之一,它是一个双向的可读写的通道,是InputStream 和 OutputStream的模拟;通道的数据读写都是要经过缓存的;

    缓存Buffer

    用于存储数据的容器,面向块处理的思想核心;

    选择器selector

    一个selector可以管理多个channel;可使用单独的线程来管理多个channel;

    

3,NIO的用法

   实现复制文件

package com.dom.nio;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
/**
 * 使用nio来实现文件的copy
 * 
 * @author Administrator
 * **/

public class CopyFile {

    public static void main(String[]ags){
        try {
            //创建文件
            File newFile = new File("F://nio.txt");
            if(!newFile.exists()){
                newFile.createNewFile();
            }
             
            //获得输入文件流通道
            @SuppressWarnings("resource")
            FileChannel fiChannel = new FileInputStream(newFile).getChannel();
            //和获取输出文件流通道
            @SuppressWarnings("resource")
            FileChannel foChannel = new FileOutputStream("F://newNio.txt").getChannel();

            fiChannel.transferTo(0 , fiChannel.size(), foChannel);
            
            foChannel.close();
            fiChannel.close();
            
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        
    }
}
package com.dom.nio;

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;

/**
 * nio服务端代码
 * 
 * @author Administrator
 * **/
public class NIOServer {
    
    private Selector selector;
    private ByteBuffer tempBuffer = ByteBuffer.allocate(1024);  
    /**
     * 对象的多路复用器。 
     * 可通过调用此类的 open 方法创建选择器,该方法将使用系统的默认选择器提供者创建新的选择器。
     * 也可通过调用自定义选择器提供者的 openSelector 方法来创建选择器。
     * 通过选择器的 close 方法关闭选择器之前,它一直保持打开状态。
     *
     * 注意:SelectionKey 对象来表示可选择通道到选择器的注册
     *    选择器维护了三个选择键集合 键集 以选择键集 (selectedKeys) 已取消键集;
     *    不管是通过关闭某个键的通道还是调用该键的 cancel 方法来取消键,该键都被添加到其选择器的已取消键集中。取消某个键会导致在下一次选择操作期间注销该键的通道,而在注销时将从所有选择器的键集中移除该键。
     * 获得server socket通道
     * 
     * @param port 端口
     * @throws IOException 
     * **/
    public void InitSelector(int port) throws IOException{
        ServerSocketChannel serverChannel = ServerSocketChannel.open(); 
        //调整通道的堵塞模式   非堵塞模式
        serverChannel.configureBlocking(false);
        //绑定端口
        serverChannel.bind(new InetSocketAddress(port));
        //获取通道管理器
        this.selector = Selector.open();
        //把通道注册到管理器 并设置关注事件   
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);//字段摘要  OP_ACCEPT 用于套接字接受操作的操作集位。 OP_CONNECT 用于套接字连接操作的操作集位。 OP_READ 用于读取操作的操作集位。OP_WRITE  用于写入操作的操作集位。 
    }
    /**
     * 监听
     * 
     * @author Administrator
     * @throws IOException 
     * **/
    public void listten() throws IOException{
        for(;;){
            selector.select();//选择器开始选择   集体要做三个事情1,将已取消键集中的每个键从所有键集中移除 2,更新每个剩余通道的准备就绪信息,3,将需要删除的任意键添加到已取消键集中
            Iterator iter = selector.selectedKeys().iterator();
            while(iter.hasNext()){
                SelectionKey key = (SelectionKey) iter.next();  
                iter.remove();  
                handle(key);//处理事件  
            }
        }
    }
    
    /**
     * 处理监听事件
     * 
     * @author Administrator
     * @throws IOException 
     * **/
    public void handle(SelectionKey key) throws IOException{
        if (key.isValid()) {
            if (key.isAcceptable()) {// 否已准备好接受新的套接字连接
                ServerSocketChannel server = (ServerSocketChannel) key.channel();
                SocketChannel channel = server.accept();
                // 设置非阻塞模式
                channel.configureBlocking(false);
                channel.register(selector, SelectionKey.OP_READ);

            } else if (key.isReadable()) {// 通道是否已准备好进行读取
                SocketChannel channel = (SocketChannel) key.channel();
                int count = channel.read(tempBuffer);
                if (count > 0) {
                    tempBuffer.flip();
                    String name = tempBuffer.toString();
                     System.out.println("接收到的信息是:"+name);
                    SelectionKey sKey = channel.register(selector,SelectionKey.OP_WRITE);
                    sKey.attach(name);
                } else {
                    channel.close();
                }

                tempBuffer.clear();
            } else if (key.isWritable()) {// 写操作准备完成
                SocketChannel channel = (SocketChannel) key.channel();
                ByteBuffer block = ByteBuffer.allocate(1024);
                block.put("哈哈哈,我想认识一下NIO".getBytes());
                channel.write(block);
            }
        }
    }
    public static void main(String[] args) {
        NIOServer service = new NIOServer();
        try {
            service.InitSelector(8085);
            service.listten();
        } catch (IOException e) {
            
            e.printStackTrace();
        }
    }

}

    

package com.dom.nio;

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.SocketChannel;
import java.util.Iterator;


/**
 * 客户端
 * 
 * @author Administrator
 * **/
public class NIOClient {

    static InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 8085);  
    static class client implements Runnable{

        @Override
        public void run() {
            try {
                SocketChannel clientChannel = SocketChannel.open();
                clientChannel.configureBlocking(false);
                Selector selector = Selector.open(); 
                //注册  设置关注事件类型
                clientChannel.register(selector, SelectionKey.OP_CONNECT);
                clientChannel.connect(addr);
                
                ByteBuffer buffer = ByteBuffer.allocate(1024); 
                int total = 0; 
                String msg = "";
                _FOR:for (;;) {
                     selector.select();  
                     Iterator iter = selector.selectedKeys().iterator();
                     while (iter.hasNext()) {  
                            SelectionKey key = (SelectionKey) iter.next();  
                            iter.remove();  
                            if (key.isConnectable()) {  
                                SocketChannel channel = (SocketChannel) key.channel();  
                                if (channel.isConnectionPending()){
                                    channel.finishConnect();
                                }
                                channel.write(buffer.put("我是从客户端来的请求".getBytes()));  
                                channel.register(selector, SelectionKey.OP_READ);  
                            } else if (key.isReadable()) {  
                                SocketChannel channel = (SocketChannel) key.channel();  
                                int count = channel.read(buffer);  
                                if (count > 0) {  
                                    total += count;  
                                    buffer.flip();  
                                    while (buffer.remaining() > 0) {  
                                        byte b = buffer.get();  
                                        //msg += (char) b;    
                                    }  
      
                                    buffer.clear();  
                                } else {  
                                    //channel.close();  
                                    break _FOR;  
                                }  
                            }  
                        }  
                    }  
                System.out.println(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
    }
    public static void main(String[] args) {
         new Thread(new client()).start();  
    }

}



你可能感兴趣的:(java.nio)