JAVA NIO

来源:互联网 发布:淘宝网玩具小马会走 编辑:程序博客网 时间:2024/06/14 12:52

Java 提供了NIO概念,也即是非阻塞IO概念。并引入了对文件和socket的一些封装。本文将详细介绍NIO。


Channel

Channel 本质上实现了对句柄的封装。Linux系统中用一个正式fd来描述文件或者网络套接字的唯一封装。Channel大体的意思也是对fd的封装。
Channel有四种,具体为:

ServerSocketChannel //Socket 服务器版本
SocketChannel   //Socket 客户端版本
FileChannel     //文件Channel
DatagramChannel    //UDP 

Buffer

Buffer 为读取Socket或者文件的一块内存。每个基本数据都有对应的Buffer。 但常用的只有ByteBuffer,按字节来读数据。
Buffer的方法需要灵活记忆:
Buffer的三个成员变量position, limit 和Capacity. Capacity为这块Buffer的内存大小。
读模式下postion 为当前读到buffer位置的指针,limit为可读数据。
写模式下postion 为当前写到buffer的位置,limit为capacity.

flip()函数写模式向读模式切换。
rewind()函数为读模式下,重新开始读。
clear() 清空所有数据
compact() 把没读的数据拷贝到buffer的开始。
Mark(), Reset()下一个书签功能,回到书签位置继续读。

FileChannel 实例

读文件并打印到控制台。
public static void testChannel() throws IOException{RandomAccessFile raf = new RandomAccessFile("/home/dumplog.py","r");FileChannel fc = raf.getChannel();ByteBuffer bf =ByteBuffer.allocate(16);int len;while((len=fc.read(bf))!=-1){bf.flip();while(bf.hasRemaining())System.out.print((char)bf.get());bf.clear();}raf.close();fc.close();}


SocketChannel 实例

实例接受客户端数据,并打印出来,然后返回一个数据。为了避免复杂,并没有写客户端程序,大家可以用telnet代替。telnet到这个端口,发送数据来测试。当读到的数据长度或者写的数据长度为-1时,意味着链接断开,需要关闭channel.

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 NIOTest {        public static void main(String[] args) throws IOException {                    Selector select = Selector.open();          ServerSocketChannel listenChannel = ServerSocketChannel.open();          listenChannel.configureBlocking(false);          listenChannel.socket().bind(new InetSocketAddress(8080));          listenChannel.socket().setReuseAddress(true);          listenChannel.register(select, SelectionKey.OP_ACCEPT);          while(true)          {              select.select();              Iterator<SelectionKey> it = select.selectedKeys().iterator();//select.keys().iterator();              while(it.hasNext())              {                  SelectionKey key = it.next();                  it.remove();                  if(key.isAcceptable())                  {                      ServerSocketChannel channel = (ServerSocketChannel) key.channel();                      SocketChannel clientChannel = channel.accept();                      clientChannel.configureBlocking(false);                      //clientChannel.write(ByteBuffer.wrap(new String("hello,trender").getBytes()));                      clientChannel.register(select, SelectionKey.OP_READ);                  }                  else if(key.isReadable())                  {                      SocketChannel channel = (SocketChannel) key.channel();                        // \u521b\u5efa\u8bfb\u53d6\u7684\u7f13\u51b2\u533a                        ByteBuffer buffer = ByteBuffer.allocate(1024);                      try                      {                          int num = channel.read(buffer);                        if(num==-1)                        {                        channel.close();                        continue;                        }                        byte[] data = buffer.array();                            String msg = new String(data).trim();                            System.out.println("\u670d\u52a1\u7aef\u6536\u5230\u4fe1\u606f\uff1a"+msg);                            ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes());                            channel.write(outBuffer);                          channel.register(select, SelectionKey.OP_WRITE);                                                }                      catch(Exception e)                      {                          System.out.print(e);                          continue;                      }                                        }                  else if (key.isWritable())                  {                      SocketChannel channel = (SocketChannel) key.channel();                      try                      {                          int len =channel.write(ByteBuffer.wrap(new String("hello trender\n").getBytes()));                        if(len<0)                        {                        channel.close();                        continue;                        }                        channel.register(select, SelectionKey.OP_READ);                    }catch(Exception e)                      {                          System.out.print(e);                      }                  }              }                        }      }    }  



小结

本文只是做了最简单的概述,可以让大家快速了解JAVA NIO,代码中还用到了Selector,其实和unix中select 函数一个道理,并没有深入。
建议从事网络相关开发,还需多看代码,最后把java.nio看代码通读下。


0 0