NIO:同步非壅闭IO
  来源:BIO是同步壅闭IO利用,当线程在处理任务时,另一方会壅闭着等待该线程的履行结束,为了前进效率,,JDK1.4后,引入NIO来提高数据的通讯功能
  NIO中接收Reactor方案形式,注册的汇集点为Selector,NIO有三个紧张构成部门:Channel(通道)、Buffer(缓冲区)、Selector(选择器)
  Reactor方案形式:Reactor形式是一种被动事情处理形式,即当某个特定事情发作时触发事情,可参考,https://blog.csdn.net/feimataxue/article/details/7642638,https://www.cnblogs.com/bitkevin/p/5724410.html
  NIO接收了轮询的方法来调查事情是否履行结束,如:A让B打印某个文件,BIO会不断等待着B返回,期间自己不做其他事变,而NIO则会不断的问询B是否完成,未完成则处理自己的时,直至B完成
  Channel(通道):Channel是一个目标,能够通过它读取和写入数据
  Selector(目标选择器):Selector是一个目标,它能够注册到很多个Channel上,监听各个Channel上发作的事情,并且能够或许根据事情状况决议Channel读写
  代码实现:(此实现参考网络上可用的例子)
  NIO客户端实现:
  packagecom.learn.nio.client;
  importcom.study.info.HostInfo;
  importcom.study.util.InputUtil;
  importjava.net.InetSocketAddress;
  importjava.nio.ByteBuffer;
  importjava.nio.channels.SocketChannel;
  publicclassNIOEchoClient{
  publicstaticvoidmain(String[]args)throwsException{
  SocketChannelclientChannel=SocketChannel.open();
  clientChannel.connect(newInetSocketAddress(HostInfo.HOST_NAME,HostInfo.PORT));
  ByteBufferbuffer=ByteBuffer.allocate(50);
  booleanflag=true;
  while(flag){
  buffer.clear();
  Stringinput=InputUtil.getString("请输入待发送的信息:").trim();
  buffer.put(input.getBytes());//将数据存入缓冲区
  buffer.flip();//重置缓冲区
  clientChannel.write(buffer);//发送数据
  buffer.clear();
  intread=clientChannel.read(buffer);
  buffer.flip();
  System.err.print(newString(buffer.array(),0,read));
  if("byebye".equalsIgnoreCase(input)){
  flag=false;
  }
  }
  clientChannel.close();
  }
  }
  NIO服务端实现:
  packagecom.learn.nio.server;
  importcom.study.info.HostInfo;
  importjava.net.InetSocketAddress;
  importjava.nio.ByteBuffer;
  importjava.nio.channels.SelectionKey;
  importjava.nio.channels.Selector;
  importjava.nio.channels.ServerSocketChannel;
  importjava.nio.channels.SocketChannel;
  importjava.util.Iterator;
  importjava.util.Set;
  importjava.util.concurrent.ExecutorService;
  importjava.util.concurrent.Executors;
  publicclassNIOEchoServer{
  privatestaticclassEchoClientHandleimplementsRunnable{
  //客户端
  privateSocketChannelclientChannel;
  //循环竣事标记
  privatebooleanflag=true;
  publicEchoClientHandle(SocketChannelclientChannel){
  this.clientChannel=clientChannel;
  }
  @Override
  publicvoidrun(){
  ByteBufferbyteBuffer=ByteBuffer.allocate(50);
  try{
  while(this.flag){
  byteBuffer.clear();
  intread=this.clientChannel.read(byteBuffer);
  Stringmsg=newString(byteBuffer.array(),0,read).trim();
  StringoutMsg="【Echo】"+msg+"\n";//回应信息
  if("byebve".equals(msg)){
  outMsg="会话竣事,下次再见!";
  this.flag=false;


  }
  byteBuffer.clear();
  byteBuffer.put(outMsg.getBytes());//回传信息放入缓冲区
  byteBuffer.flip();
  this.clientChannel.write(byteBuffer);//回传信息
  }
  }catch(Exceptione){
  e.printStackTrace();
  }
  }
  }
  publicstaticvoidmain(String[]args)throwsException{
  //为了功能问题及相应时刻,设置固定巨细的线程池
  ExecutorServiceexecutorService=Executors.newFixedThreadPool(10);
  //NIO根据Channel控制,所以有Selector办理悉数的Channel
  ServerSocketChannelserverSocketChannel=ServerSocketChannel.open();
  //设置为非壅闭形式
  serverSocketChannel.configureBlocking(false);
  //设置监听端口
  serverSocketChannel.bind(newInetSocketAddress(HostInfo.PORT));
  //设置Selector办理悉数Channel
  Selectorselector=Selector.open();
  //注册并设置毗邻时处理
  serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
  System.out.println("服务发动乐成,监听端口为:"+HostInfo.PORT);
  //NIO运用轮询,当有恳求毗邻时,则发动一个线程
  intkeySelect=0;
  while((keySelect=selector.select())>0){
  SetselectionKeys=selector.selectedKeys();
  Iteratoriterator=selectionKeys.iterator();
  while(iterator.hasNext()){
  SelectionKeynext=iterator.next();
  if(next.isAcceptable()){//假如是毗邻的
  SocketChannelaccept=serverSocketChannel.accept();
  if(accept!=null){
  executorService.submit(newEchoClientHandle(accept));
  }
  iterator.remove();
  }
  }
  }
  executorService.shutdown();
  serverSocketChannel.close();
  }
  }
  工具类:
  packagecom.study.util;
  importjava.io.BufferedReader;
  importjava.io.IOException;
  importjava.io.InputStreamReader;
  publicclassInputUtil{
  privatestaticfinalBufferedReaderKEYBOARD_INPUT=newBufferedReader(newInputStreamReader(System.in));
  privateInputUtil(){
  }
  publicstaticStringgetString(Stringprompt){
  booleanflag=true;//数据承受标记
  Stringstr=null;
  while(flag){
  System.out.println(prompt);
  try{
  str=KEYBOARD_INPUT.readLine();//读取一行数据
  if(str==null||"".equals(str)){
  System.out.println("数据输入过错,不允许为空!");
  }else{
  flag=false;
  }
  }catch(IOExceptione){
  e.printStackTrace();
  }
  }
  returnstr;
  }
  }
  packagecom.study.info;
  publiccalssHostInfo{
  publicstaticfinalStringHOST_NAME="localhost";
  publicstaticfinalintPORT=9999;
  }

posted on 2020-04-17 15:15  林口  阅读(205)  评论(0编辑  收藏  举报