NIO

Posted theqi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NIO相关的知识,希望对你有一定的参考价值。

客户端代码

    
public static void client()
    {
        ByteBuffer buffer = ByteBuffer.allocate(1024);//给buffer缓冲区分配空间
        SocketChannel socketChannel = null;
        try
        {
            socketChannel = SocketChannel.open();//打开socketChannel
            socketChannel.configureBlocking(false);//配置这个信道为非阻塞信道
            socketChannel.connect(new InetSocketAddress(InetAddress.getLocalHost(),8080));//连接服务器
            if(socketChannel.finishConnect())//用来确认通道连接已经建立的
            {
                int i=0;
                while(true)
                {
                    TimeUnit.SECONDS.sleep(1);//延时一秒
                    String info = "I‘m "+i+++"-th information from client";
                    buffer.clear();//将buffer中没读的数据遗忘掉(limit又会回到capacity)
                    buffer.put(info.getBytes());//将字符串存如buffer中
                    //调用下面这个函数会让position为0,limit为之前position的值
                    //这样我们只可以读出从position到limit这些位置的数据,也就是之前我们写的数据
                    buffer.flip();
                    while(buffer.hasRemaining()){//判断当前元素是否在限制范围内(positon是否limit)
                        System.out.println(buffer);
                        socketChannel.write(buffer);//将buffer中的数据写如socketChannel中
                    }
                }
            }
        }
        catch (IOException | InterruptedException e)
        {
            e.printStackTrace();
        }
        finally{
            try{
                if(socketChannel!=null){
                    socketChannel.close();
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }

服务器代码:

public class Main
{
    private static final int BUF_SIZE=1024;
    private static final int PORT = 8080;
    private static final int TIMEOUT = 3000;
    public static void main(String[] args)
    {
        selector();
    }
    public static void handleAccept(SelectionKey key) throws IOException
    {
        ServerSocketChannel ssChannel = (ServerSocketChannel)key.channel();//获取发生网络事件的ssc
        SocketChannel sc = ssChannel.accept();//通过accept获取SocketChannel
        sc.configureBlocking(false);
        //将sc注册到selector中,注册读事件,同时附加参数为一个申请的1024的buffer空间
        sc.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocateDirect(BUF_SIZE));
    }
    public static void handleRead(SelectionKey key) throws IOException{
        SocketChannel sc = (SocketChannel)key.channel();//获取发生网络事件的sc
        ByteBuffer buf = (ByteBuffer)key.attachment();//获取附加参数
        long bytesRead = sc.read(buf);//从Channel中读取数据到buffer中
        while(bytesRead>0){
            buf.flip();
            while(buf.hasRemaining()){
                System.out.print((char)buf.get());
            }
            System.out.println();
            buf.clear();
            bytesRead = sc.read(buf);//继续读取
        }
        if(bytesRead == -1){//客户端数据发送完毕并主动断开socket
            sc.close();
        }
    }
    public static void handleWrite(SelectionKey key) throws IOException{
        ByteBuffer buf = (ByteBuffer)key.attachment();
        buf.flip();
        SocketChannel sc = (SocketChannel) key.channel();
        while(buf.hasRemaining()){
            sc.write(buf);//通过buffer写入数据到信道中
        }
        buf.compact();//将所有处理的数据拷贝到Buffer起始处。然后将position设到最后一个未读元素正后面。
                      //limit属性依然像clear()方法一样,设置成capacity
    }
    public static void selector() {
        Selector selector = null;//与其一起使用的通道一定是非阻塞的(FileChannel就不行)
        ServerSocketChannel ssc = null;
        try{
            selector = Selector.open();//打开selector
            ssc= ServerSocketChannel.open();//打开SSC(客户端那边是SocketChannel)
            ssc.socket().bind(new InetSocketAddress(PORT));//绑定端口号
            ssc.configureBlocking(false);//设置非阻塞
            SelectionKey s = ssc.register(selector, SelectionKey.OP_ACCEPT);// 选择注册什么事件到selector中
            while(true){
                if(selector.select(TIMEOUT) == 0){
                    System.out.println("==");
                    continue;
                }
                Iterator<SelectionKey> iter = selector.selectedKeys().iterator();//遍历发生事件的sK
                while(iter.hasNext()){
                    SelectionKey key = iter.next();
                    if(key.isAcceptable()){
                        handleAccept(key);
                    }
                    if(key.isReadable()){
                        handleRead(key);
                    }
                    if(key.isWritable() && key.isValid()){
                        handleWrite(key);
                    }
                    if(key.isConnectable()){
                        System.out.println("isConnectable = true");
                    }
                    iter.remove();
                }
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try{
                if(selector!=null){
                    selector.close();
                }
                if(ssc!=null){
                    ssc.close();
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}

 

以上是关于NIO的主要内容,如果未能解决你的问题,请参考以下文章

NIO 聊天室代码实现

Java异步非阻塞IO NIO使用与代码分析

nio原理和示例代码

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

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

Netty——网络编程 NIO(Selector处理read事件)代码示例