JAVA NIO

3 篇文章 0 订阅

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看代码通读下。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值