分享

Bio、Nio、Aio的用法系列之NIO客户端(三)

 太极混元天尊 2018-05-28

NIO客户端的实现

上一篇文章我们提到了NIO,大家应该对NIO有了一定的了解,接下来我们继续学习NIO的客户端实现

1、代码展示

首先我们还是先启动一个线程

public class NioServer {
public static void main(String [] args){
   //启动一个线程
   new Thread(new NioServerHandle()).start();
}

}

处理类

public class NioServerHandle implements Runnable{private ServerSocketChannel serverSocketChannel;
private Selector selector;
boolean stop  = false;
//初始化注册
public NioServerHandle(){
   try {
       //获取ServerSocketChannel对象
       serverSocketChannel = ServerSocketChannel.open();
       //绑定ip
       serverSocketChannel.socket().bind(new InetSocketAddress('127.0.0.1',8989));
       //设置为非阻塞
       serverSocketChannel.configureBlocking(false);
       //获取Selector
       selector = Selector.open();
       //将管道注册到多路复用器selector上
       serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
   } catch (IOException e) {
       e.printStackTrace();
       System.exit(1);
   }
}
public void stop(){
   this.stop = true;
}
@Override
public void run() {
   //轮询key
   while (!stop){
       try {
           //设置超时时间
           selector.select(1000);
           //获取所有key
           Set selectionKeys = selector.selectedKeys();
           //遍历
           Iterator
it = selectionKeys.iterator();
           SelectionKey selectionKey = null;
           while (it.hasNext()){
               selectionKey = it.next();
               //获取到就绪数组进行操作,并移除
               it.remove();
               try {
                   handle(selectionKey);
               }catch (Exception e){
                   selectionKey.cancel();
                   selectionKey.channel().close();
               }
           }
       } catch (IOException e) {
           e.printStackTrace();
       }
   }
}
/**
* 处理
* @param key
* @throws Exception
*/

public void handle(SelectionKey key) throws Exception{
   if (key.isValid()){
       if (key.isAcceptable()){
           //获取ServerSocketChannel
           ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
           //接受请求
           SocketChannel sc = ssc.accept();
           //设置为非阻塞
           sc.configureBlocking(false);
           //注册到多路复用器
           sc.register(selector,SelectionKey.OP_READ);
       }
       //read data
       if (key.isReadable()){
           //得到SocketChannel
           SocketChannel sc = (SocketChannel) key.channel();
           //设置字节缓冲区
           ByteBuffer readBuffer = ByteBuffer.allocate(1024);
           //将通道的数据读取码流
           int readByte = sc.read(readBuffer);
           //对于大于0的情况进行编解码
           if (readByte > 0){
               //将当前的缓冲区的limit设置为0,让后面进行读取
               readBuffer.flip();
               //根据缓冲区的可读大小设置字节数组
               byte [] bytes = new byte[readBuffer.remaining()];
               //get将读取的数据放入字节数组
               readBuffer.get(bytes);
               //将字节数组按照UTF-8的格式输出到body
               String body = new String(bytes,'UTF-8');
               System.out.print('The Time server recevive order:'+body);
               String currentTime = 'query'.equals(body)?new java.util.Date(System.currentTimeMillis()).toString():'No';
               //进行输出操作
               doWrite(sc,currentTime);
           }else if (readByte < 0 ){
               key.cancel();
               sc.close();
           }else {
           }
       }
   }
}
/**
* 将数据返回给客户端
* @param sc
* @param currentTime
* @throws Exception
*/

public void doWrite(SocketChannel sc,String currentTime) throws Exception{
   if (currentTime != null && currentTime.trim().length() > 0){
       //转换为字节数组,放到缓冲区
       byte [] bytes = currentTime.getBytes();
       ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
       byteBuffer.put(bytes);
       byteBuffer.flip();
       sc.write(byteBuffer);
   }
}}


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多