NioSocket相关知识

来源:互联网 发布:landmark软件安装 编辑:程序博客网 时间:2024/06/05 02:00

一、Nio简介

nio 是non-blocking的简称,在jdk1.4 里提供的新api 。Sun 官方标榜的特性如下: 为所有的原始类型提供(Buffer)缓存支持。字符集编码解码解决方案。 Channel :一个新的原始I/O 抽象。 支持锁和内存映射文件的文件访问接口。 提供多路(non-bloking) 非阻塞式的高伸缩性网络I/O 。

java.nio包是Java在1.4之后增加的,用来提高I/O操作的效率。在nio包中主要包括以下几个类或接口:

* Buffer:缓冲区,用来临时存放输入或输出数据。* Charset:用来把Unicode字符编码和其它字符编码互转。* Channel:数据传输通道,用来把Buffer中的数据写入到数据源,或者把数据源中的数据读入到Buffer。* Selector:用来支持异步I/O操作,也叫非阻塞I/O操作。

nio包中主要通过下面两个方面来提高I/O操作效率:

* 通过Buffer和Channel来提高I/O操作的速度。* 通过Selector来支持非阻塞I/O操作。

传送门:NIO与IO的区别

二、NioSocket

NIO为socket提供了新的连接方式。使用NioSocket的流程如下:

Created with Raphaël 2.1.0开始建立ServerSocketChannel设置相应的参数。创建Selector并注册到ServerSocketChannel上。调用Selector的select方法等待请求,可以制定超时时间。Selector接收到请求后使用selectedKeys返回SelectionKey集合。使用SelectionKey获取到Channel、Selector和操作类型并进行具体的操作。结束

三、服务器示例代码

package com.frank.java.util;/** * Created by Administrator on 2016/6/24. */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.nio.charset.Charset;import java.util.Iterator;public class NIOServer {    public static void main(String[] args) throws Exception{        //创建ServerSocketChannel,监听8080端口        ServerSocketChannel ssc=ServerSocketChannel.open();        ssc.socket().bind(new InetSocketAddress(8081));        //设置为非阻塞模式        ssc.configureBlocking(false);        //为ssc注册选择器        Selector selector=Selector.open();        ssc.register(selector, SelectionKey.OP_ACCEPT);        //创建处理器        Handler handler = new Handler(1024);        while(true){            // 等待请求,每次等待阻塞3s,超过3s后线程继续向下运行,如果传入0或者不传参数将一直阻塞            if(selector.select(3000)==0){                System.out.println("等待请求超时。。。");                continue;            }            System.out.println("处理请求。。。");            // 获取待处理的SelectionKey            Iterator<SelectionKey> keyIter=selector.selectedKeys().iterator();            while(keyIter.hasNext()){                SelectionKey key=keyIter.next();                try{                    // 接收到连接请求时                    if(key.isAcceptable()){                        handler.handleAccept(key);                    }                    // 读数据                    if(key.isReadable()){                        handler.handleRead(key);                    }                } catch(IOException ex) {                    keyIter.remove();                    continue;                }                // 处理完后,从待处理的SelectionKey迭代器中移除当前所使用的key                keyIter.remove();            }        }    }    private static class Handler {        private int bufferSize = 1024;        private String  localCharset = "UTF-8";        public Handler(){}        public Handler(int bufferSize){            this(bufferSize, null);        }        public Handler(String  LocalCharset){            this(-1, LocalCharset);        }        public Handler(int bufferSize, String  localCharset){            if(bufferSize>0)                this.bufferSize=bufferSize;            if(localCharset!=null)                this.localCharset=localCharset;        }        public void handleAccept(SelectionKey key) throws IOException {            SocketChannel sc=((ServerSocketChannel)key.channel()).accept();            sc.configureBlocking(false);            sc.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(bufferSize));        }        public void handleRead(SelectionKey key) throws IOException {            // 获取channel            SocketChannel sc=(SocketChannel)key.channel();            // 获取buffer并重置            ByteBuffer buffer=(ByteBuffer)key.attachment();            buffer.clear();            // 没有读到内容则关闭            if(sc.read(buffer)==-1){                sc.close();            } else {                // 将buffer转换为读状态                buffer.flip();                // 将buffer中接收到的值按localCharset格式编码后保存到receivedString                String receivedString =                Charset.forName(localCharset).newDecoder().decode(buffer).toString();                System.out.println("received from client: " + receivedString);                // 返回数据给客户端                String sendString = "received data: " + receivedString;                buffer = ByteBuffer.wrap(sendString.getBytes(localCharset));                sc.write(buffer);                // 关闭Socket                sc.close();            }        }    }}
0 0