java的nio实现
2016-06-17 20:30
441 查看
前言:最近在研究java netty这个网络框架,第一篇先介绍java的nio。
java nio在jdk1.4引入,其实也算比较早的了,主要引入非阻塞io和io多路复用。内部基于reactor模式。
nio核心:
- buffer
- channel
- selector
buffer:
类似网络编程中的缓冲区,有
ByteBuffer 字节
CharBuffer 字符
IntBuffer
DoubleBuffer…
常用的有ByteBuffer和CharBuffer
java nio buffer是开辟了一块空间,内部有4个标记,分别为position,limit,capicity,mask。
position是当前读缓冲区位置,limit是数据的结尾,表示最多能读到limit位置,capacity是缓冲区的容量,在position和limit之间还会有mask用来标记一个位置,可以移动position到达mask位置
buffer有两个重要的方法clear和flip
clear()方法没有清空数据而是将position置为0,limit置为capacity,
为再次向buffer装数据做好准备
flip()方法在装载完数据后,将limit设为当前position位置,然后将position设置为0,简单来说就是flip()为从buffer中取出数据做好准备。
>
channel:
类似网络编程中的套接字,Java nio中称为Channel(通道),个人认为这样更加方便我们理解,服务器和客户端之间通过Channel来传输数据。
channel 有
FileChannel 文件管道
DatagramChannel 数据报管道
SocketChannel socket管道
ServerSocketChannel 服务端socket管道
channel可以直接文件的部分或全部映射为buffer
注意:
程序不能直接访问channel的数据,channel必须和buffer结合起来使用。
所有的channel都不应该用构造器,从传统的流节点Inputstream 等来获取channel
selector:
事件分发收集器,内部封装的epoll。我们可以往上面注册事件,然后监听多个channel通道上的事件等。
时序图
注:图片非原创
从时序图可以看出java nio和我们平时写的网络编程很像。
转自:http://blog.csdn.net/wwh578867817/article/details/47071417
java nio在jdk1.4引入,其实也算比较早的了,主要引入非阻塞io和io多路复用。内部基于reactor模式。
nio核心:
- buffer
- channel
- selector
buffer:
类似网络编程中的缓冲区,有
ByteBuffer 字节
CharBuffer 字符
IntBuffer
DoubleBuffer…
常用的有ByteBuffer和CharBuffer
java nio buffer是开辟了一块空间,内部有4个标记,分别为position,limit,capicity,mask。
position是当前读缓冲区位置,limit是数据的结尾,表示最多能读到limit位置,capacity是缓冲区的容量,在position和limit之间还会有mask用来标记一个位置,可以移动position到达mask位置
buffer有两个重要的方法clear和flip
clear()方法没有清空数据而是将position置为0,limit置为capacity,
为再次向buffer装数据做好准备
flip()方法在装载完数据后,将limit设为当前position位置,然后将position设置为0,简单来说就是flip()为从buffer中取出数据做好准备。
>
channel:
类似网络编程中的套接字,Java nio中称为Channel(通道),个人认为这样更加方便我们理解,服务器和客户端之间通过Channel来传输数据。
channel 有
FileChannel 文件管道
DatagramChannel 数据报管道
SocketChannel socket管道
ServerSocketChannel 服务端socket管道
channel可以直接文件的部分或全部映射为buffer
注意:
程序不能直接访问channel的数据,channel必须和buffer结合起来使用。
所有的channel都不应该用构造器,从传统的流节点Inputstream 等来获取channel
selector:
事件分发收集器,内部封装的epoll。我们可以往上面注册事件,然后监听多个channel通道上的事件等。
时序图
注:图片非原创
从时序图可以看出java nio和我们平时写的网络编程很像。
java nio实现简单的回射服务器
import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.channels.spi.SelectorProvider; import java.nio.charset.Charset; import java.util.Set; /** * Created by wwh on 15-7-25. */ public class NioSocket { //字符序列和字节序列的编码和解码 private Charset charset = Charset.forName("UTF-8"); void run(String ip, int port) throws IOException { try { //创建服务端套接字 ServerSocketChannel server = ServerSocketChannel.open(); //绑定ip和端口 server.socket().bind(new InetSocketAddress(ip, port)); //设置非阻塞 server.configureBlocking(false); //创建selector事件选择器 Selector selector = Selector.open(); //将自己的监听套接字注册到selector上,监听 accept事件 //SelectionKey代表SelectableChannel和Selector的关系,Selectable是Selector可监听的事件channel. server.register(selector, SelectionKey.OP_ACCEPT); while(selector.select() > 0){ //selector.select()返回事件 for(SelectionKey sk : selector.selectedKeys()) { //从事件集合中删除正要处理的事件 selector.selectedKeys().remove(sk); //判断事件的类型,依次处理 if(sk.isAcceptable()){ //如果事件为接受连接accpet事件 System.out.println("accpet 事件"); //调用accept接受请求连接 SocketChannel client = server.accept(); //设置为非阻塞 client.configureBlocking(false); //向selector上注册读事件 client.register(selector, SelectionKey.OP_READ); //将sk对应的channel设置为准备接受其他请求 sk.interestOps(SelectionKey.OP_ACCEPT); } if(sk.isReadable()){ //如果事件为可读事件 System.out.println("read 事件"); SocketChannel client = (SocketChannel)sk.channel(); //定义缓冲区 ByteBuffer buffer = ByteBuffer.allocate(1024); String mesg = ""; try { while (client.read(buffer) > 0) { buffer.flip(); mesg += charset.decode(buffer); } System.out.println("收到:" + mesg); sk.interestOps(SelectionKey.OP_READ); }catch (IOException e){ //如果出现异常,则取消当前的client连接 sk.cancel(); if(sk.channel() != null){ sk.channel().close(); } } //回复给发来消息的client client.write(charset.encode(mesg)); System.out.println("回复:" + mesg); } } } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws IOException { NioSocket Server = new NioSocket(); Server.run("192.168.10.75", 10000); } }
转自:http://blog.csdn.net/wwh578867817/article/details/47071417
相关文章推荐
- 华为桌面云中和Java相关的问题
- 查看Java的默认字符编码
- Java 多线程编程之七:死锁(附源代码)
- java中的抽象类和接口
- java hashtable实现内存缓存
- Struts1内部原理详解
- FileUpload系列:(2)文件上传示例
- Java 进行 RSA 加解密的例子
- Java并发编程-正确理解volatile关键字的两层语义
- 关于springmvc跨域
- Java 理论和实践:线程池和工作队列
- FileUpload系列:(1)文件上传的思路和示例
- Java解析Json字符串
- 【每天学一点】JAVA-DOM4J&XPath的XML处理
- spring mvc 返回 json
- Java 并发工具包 java.util.concurrent 用户指南
- Java 语言中 List、Set 和 Map 的区别
- Java反射(六)----- 通过反射了解集合泛型的本质
- Java堆排序
- Java 判断两个字符串是否由相同的字符组成