前言:近期在研究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和我们平时写的网络编程非常像。


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);
}
}

最新文章

  1. 分布式系统理论基础 - CAP
  2. Hive索引功能测试
  3. linux查看主板型号及内存硬件信息
  4. 伪集群zookeeper模式下codis的部署安装
  5. Android中Handler的消息处理
  6. 反人类的MyEclipse之-eclipse设置花括号换行显示
  7. 有用的shell命令
  8. DWZ (JUI) 教程 DWZ中dialog层的刷新
  9. CSS3中translate、transform和translation的区别和联系
  10. [JSOI2008]星球大战
  11. Linux用户root忘记密码的解决(unbuntu16.04)
  12. javascript string对象的属性与方法
  13. 注解@Transactional(rollbackFor = Exception.class) 的用法
  14. Fiddler(二)Fiddler操作界面[工具条]和[底部状态面板]说明
  15. 学习 MySQL中导入 导出CSV
  16. python模拟线性回归的点
  17. myeclipse集成jdk、tomcat8、maven、svn
  18. dir for RequestHandler and request
  19. web前端----jQuery操作标签
  20. 19 Error handling and Go go语言错误处理

热门文章

  1. 2-SAT的小总结(POJ 3683 POJ 3207)
  2. 自学Python八 爬虫大坑之网页乱码
  3. jvm堆外直接内存实现高性能接入层
  4. 酷派 5267 刷入第三方 recovery教程 刷机 ROOT
  5. Sql语句优化-查询两表不同行NOT IN、NOT EXISTS、连接查询Left Join
  6. js 事件冒泡、事件捕获、stopPropagation、preventDefault
  7. Embedded之Stack之二
  8. Luogu P1365 WJMZBMR打osu! / Easy
  9. C++调用Matlab函数求特征值
  10. Windows server 2008R2系统登录密码破解