学习记录--nio(二)

来源:互联网 发布:锐捷网络校招 编辑:程序博客网 时间:2024/05/17 03:20

         接前面的一节。 

        上面一节主要说得是基本知识。主要的传输是本地的。filechannel.。  也谈不上什么阻塞非阻塞。  这一节说说阻塞非阻塞,主要是网络传输,客户端服务端访问之类。

-----------------------------------------------------------------------------------

1.单线程阻塞--->多线程----->选择器



-----------

练习:


----1.TestBlockingNIO.java----- 这个是阻塞的,没有选择器监听------------------

package com.fjf.study;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;


import org.junit.Test;






/**
 * 先练习一个 阻塞式的Nio
 * @author fjf
 * 2017年11月27日 18:40:01
 * 
 * 自我理解   channel.read() 是数据读到buff上。channel.write() 数据从buff写到通道中,以buff作为中心
 */
public class TestBlockingNIO {
  
//客户端
@Test
public void client() throws IOException{
//1.获取网络通道
SocketChannel schannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 5858));

//2.准备数据,(获取file通道,装buff,将内容弄到网络通道中)
FileChannel incChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
ByteBuffer buff = ByteBuffer.allocate(1024);
while(incChannel.read(buff)!=-1){
buff.flip();
schannel.write(buff);
buff.clear();
}


/*schannel.shutdownOutput();

//加点料 接受服务端的反馈
int len = 0;
while((len = schannel.read(buff))!=-1){
buff.flip();
System.out.println(new String(buff.array(),0,len));
buff.clear();
}

//System.out.println("------客户端关闭");*/
//3.关闭
schannel.close();
incChannel.close();
}

//服务端
@Test
public void server() throws IOException{
//1.获取网络通道
ServerSocketChannel schannel = ServerSocketChannel.open();
//2.绑定连接
schannel.bind(new InetSocketAddress(5858));
//3.获取客户端通道
SocketChannel clientchannel = schannel.accept();

//4.把客户端通道的数据读到服务端本地
ByteBuffer buff = ByteBuffer.allocate(1024);
FileChannel outcChannel = FileChannel.open(Paths.get("2.jpg"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);
while(clientchannel.read(buff)!=-1){
buff.flip();
outcChannel.write(buff);
buff.clear();
}

System.out.println("服务端啦啦啦");
//加点料,给客户端点反馈
/*buff.put(("服务端解接受成功").getBytes());
buff.flip();
clientchannel.write(buff);*/

//5.关闭
schannel.close();
clientchannel.close();
outcChannel.close();
}



}

--------2.TestNonBlockingNIO.java--------------非阻塞--

package com.fjf.study;


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


import org.junit.Test;




/**
 * 非阻塞io    channel ,buffer,selector
 * @author fjf
 *  如果工作中用到了,一般就是用的这个
 *  2017年11月28日 17:51:22
 */
public class TestNonBlockingNIO {
   
//客户端
@Test
public void client() throws IOException{
   //1.获取网络通道
SocketChannel schannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 6868));
//2.通道切换为非阻塞模式
schannel.configureBlocking(false);

//3.指定buff
ByteBuffer buff = ByteBuffer.allocate(1024);
//4.写入数据
buff.put(new Date().toString().getBytes());
buff.flip();
schannel.write(buff);
buff.clear();
//5.关闭
schannel.close();
}

//服务端
@Test
   public void server() throws IOException{
//1.获取网络通道
  ServerSocketChannel sschannel = ServerSocketChannel.open();
 //2. 切换为非阻塞模式
  sschannel.configureBlocking(false);
  //3. 绑定连接
  sschannel.bind(new InetSocketAddress(6868));
  //4. 新建选择器
  Selector selector= Selector.open();
  //5. 注册通道,并设置监听事件
  sschannel.register(selector, SelectionKey.OP_ACCEPT);
  //6. 轮询获取已注册的所有选择器
  while(selector.select()>0){
 Iterator<SelectionKey> it=  selector.selectedKeys().iterator(); 
 
 while(it.hasNext()){
 SelectionKey sk = it.next();
 
 if(sk.isAcceptable()){
 SocketChannel clinetchannel = sschannel.accept();
 
 clinetchannel.configureBlocking(false);
 
 clinetchannel.register(selector, SelectionKey.OP_READ);
 }else if(sk.isReadable()){
 SocketChannel schannel =(SocketChannel) sk.channel();
 ByteBuffer buff = ByteBuffer.allocate(512);
 
 int len = 0;
 while((len =schannel.read(buff))!=-1){
 buff.flip();
 System.out.println(new String(buff.array(),0,len));
 buff.clear();
 }
 
 }
it.remove();  
 }
  }
 
  
}

}

---------------------------

总结:

  一、使用 NIO 完成网络通信的三个核心:
  
  1. 通道(Channel):负责连接
  
     java.nio.channels.Channel 接口:
   |--SelectableChannel
  |--SocketChannel
   |--ServerSocketChannel
   |--DatagramChannel
  
   |--Pipe.SinkChannel
   |--Pipe.SourceChannel
  
  2. 缓冲区(Buffer):负责数据的存取
  
  3. 选择器(Selector):是 SelectableChannel 的多路复用器。用于监控 SelectableChannel 的 IO 状况
  
 

原创粉丝点击