【Android】NIO相关

什么是NIO:
NIO的全称是New IO,也就是新的IO,源于JDK1.4

NIO入门:
NIO的核心类是Channel和Buffer,其中:
Channel用于读写数据,Buffer用于缓存数据

1、Channel的类型与创建方法:
//FileChannel:读写文件的Channel
FileChannel in = fileInputStream.getChannel();
FileChannel out = fileOuputStream.getChannel();

//DatagramChannel:用于进行UDP连接的Channel
DatagramChannel udp = DatagramChannel.open();

//SocketChannel:用于进行TCP连接的Channel(Client端)
SocketChannel tcpClient = SocketChannel.open();

//ServerSocketChannel:用于进行TCP连接的Channel(Server端)
ServerSocketChannel tcpServer = ServerSocketChannel.open();
2、Buffer的类型与常用方法:
一个Buffer主要由position, limit, capacity三个变量来控制读写的过程
其中,position为当前指针所在的位置,limit为实际读取的数据长度,capacity为缓冲区的总长度
Buffer的常见类型有:Byte/Char/Short/Int/Long/Float/DoubleBuffer,还有MappedByteBuffer 
ByteBuffer buffer = ByteBuffer.allocate(1024);	//创建Buffer
buffer.flip();				//将position清零,以便进行读取 
buffer.clear();				//将position和limit清零,以便进行写入
channel.read(buffer);		//从buffer中读取数据,从position的位置读取到limit的位置
channel.write(buffer);		//向buffer中写入数据,从position的位置写入到capacity的位置
3、字符集的处理:
Charset charset = Charset.forName("GBK");	//创建字符集
charset.encode(String source)				//对字符串进行编码
String result = charset.decode(buffer);		//对Buffer中的内容进行解码并返回String

NIO进阶:
NIO的最大优点是非阻塞IO,所谓非阻塞IO,是相对于阻塞IO来说的
对于传统的IO,当Server端调用accept()和read()方法时,线程都会被阻塞
而非阻塞IO的原理就是采用事件驱动机制,由Selector类来负责多个通道上事件的检测,并将事件分发给对应的Channel来处理
其中事件的类型为SelectionKey,其中包含了事件的状态信息,以及该事件对应绑定到的Channel

1、Selector的结构模型:
首先将Channel注册到Selector上(Channel的信息会被封装到SelectionKey类型的对象中)
当指定了这个Channel的请求来到时,该SelectionKey就会变成可用状态
这样Selector在轮询的时候,就可以把这个SelectionKey获取出来,并对其进行操作
这样做的好处是可以将多个Channel注册到同一个Selector上,而不用为每个Channel单独启动一个线程并让其阻塞

2、Selector的使用流程:
//创建并初始化Channel
SocketChannel client = SocketChannel.open();				//创建Channel
client.connect(new InetSocketAddress("localhost", port));	//使Channel连接到服务器

//创建Selector,并将Channel注册到Selector上
Selector selector = Selector.open();						//创建Selector
client.configureBlocking(false);							//将Channel设置成非阻塞
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);	//注册Channel
//register方法的第二个参数表示Channel可以进行的操作,共有READ,WRITE,ACCEPT和CONNECT四种操作
//在将Channel注册到Selector之前,必须保证是非阻塞的,否则将抛出IllegalBlockingModeException异常

//通过Selector轮询可以进行操作的Channel,并通过SelectionKey对Channel进行操作
while(true) {
	int readyCount = selector.select(1000); //在指定的时间内,返回可以进行操作的Channel的数量
		if(readyCount == 0) continue;		//如果没有可以进行操作的Channel,则不执行任何操作
		Iterator
  
  
   
    iter = selector.selectedKeys.iterator();
		while(iter.hasNext()){
			SelectionKey key = iter.next(); 
			if (key.isReadable()) {
				handleRead(selector, key);
			}
		}
		iter.remove();
	}
}

/** 处理接收到的消息 */
private void handleRead(Selector selector, SelectionKey key) throws Exception{
	int length = 0;
	String content = "";
	ByteBuffer readBuffer = ByteBuffer.allocateDirect(10240);
	SocketChannel channel = (SocketChannel) key.channel();

	while ((length = channel.read(readBuffer)) > 0) {
		readBuffer.flip();
		while (readBuffer.hasRemaining()) {
			int size = readBuffer.remaining();
			byte [] contentBuffer = new byte[size];
			readBuffer.get(contentBuffer);
			content = new String(contentBuffer);
			Log.i(TAG, "Message Received! Content: " + content);
		}
		readBuffer.clear();
	}

	//如果接收信息结束,则关闭Channel
	if (length < 0) {
	   Log.i(TAG, "Client disconnected!");
	   channel.close();
	}
}

  
  
3、SelectionKey的常用方法:
selectionKey.channel();			//获取其中封装的Channel对象
selectionKey.isReadable();		//判断selectionKey的注册类型是否为OP_READ
selectionKey.isWriteable();		//判断selectionKey的注册类型是否为OP_WRITE
selectionKey.isAcceptable();	//判断selectionKey的注册类型是否为OP_ACCEPT
selectionKey.isConnectable();	//判断selectionKey的注册类型是否为OP_CONNECT

Android中使用NIO的注意事项:
由于Android2.2中对IPv6的协议支持有BUG,因此在2.2中如果使用NIO,应当在类中添加以下静态代码:
static {
	//解决Android2.2系统中不能启用IPV6协议的问题
	java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
	java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
}

此外,由于Android4.0规范不允许在主线程中进行网络连接等耗时操作
因此在开发时,所有的NIO操作都应放到子线程中进行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值