NIO基础


title: "Nio"
date: 2019-07-24T16:02:33+08:00



本章内容为:《NIO基础》

作者:nuoccc

首先我们来了解一下什么是NIO;

  • NIO全程 Non-block I/O 中文意思就是无阻塞读写流,jdk1.4之后提供的新I/O
    然后在我们NIO中有三个核心对象需要掌握
  • 缓冲区 (Buffer)
  • 通道 (Channel)
  • 选择器 (Selector)
  • 这篇文章就针对上述这三点进行了解

一丶Buffer

Buffer有四个属性:1.capacity 容量 2. limit 上限 3. position 当前位置 4. mark 标记
我们就直接通过一个程序来看看Buffer的API使用方法,以及加强对Buffer的四个属性的理解

InBuffer buffer = InBuffer.allocate(8);//我们先开辟一个长度为8的整型缓冲区
//buffer的使用本质上就是创建一个数组来进行缓存
for(int i = 0;i<6;i++){
    buffer.put(i);//把当前的i放进buffer里面,这时候poition会向后移一位
    //position可以理解为栈的栈顶,是在数据的高一位
}

buffer.filp();//转化buffer的读写方式,默认为读方式,现在转化为写
while(buff.hasRemaining()){//可以理解为has.next(),判断是否还有数据
    int j = buffer.get();//从buffer里面取数据,这里j其实就是buffer每个数据的下标
    System.out.print(j+"")//输出当前j,瞅瞅是否跟我们预期一样
}

buffer.clear();//清空缓存区,重新读写
//说是清空,实际上是把当前的position又重新置为0,当put一个数据时,就会重新覆盖原来的数据
for(int i=0;i<buff.capacity();i++){
    buffer.put(i);
}
buffer.flip();
while(buffer.hasReamining()){
    int j = buffer.get();
    System.out.println(j);
}

其实Buffer还是挺好理解的,就是对一个数组进行读和写,但是我们后面的的都是基于buffer运行的。

二丶Channel

了解完Buffer之后我们来看看Channel(通道),那什么是Channel呢?
我们首先来看一个图,来看看Channel的作用:

我们可以看出程序与程序之间数据传递并不是直接传递的,而是先通过Buffer然后再在Channel之间传递
根据上图,我们就可以设计出程序来进行通讯。
常用的Channel实现类有SocketChannel ServerSocketChannel DataGramChannel FileChannel ByteChannel
我们在实际使用中来熟悉Channel的用法

首先是FileChannel 我们应该模拟一个进行读数据 一个进行写数据

我们先基于FileChaneel的读数据进行编程:

FileInputStream fis = new FileInputStream("C:\\Users\\admin\\Desktop\\1.txt");
//先创立一个输入流
FileChannel channel = fis.getChannel();//创立一个FileChannel对象跟输入流进行连接
ByteBuffer buffer = ByteBuffer.allocate(1024);//我们开辟一片缓存区
channel.read(buff);//注意这个意思是把channel对象读到的数据写入缓存区中
buffer.filp();//然后我们切换成读取模式
while(buffer.hasRemainning()){
    byte b=buffer.get();
    System.out.print((char)b);//打印一下看是否是我们文件的数据。
}
fis.close();//关闭输入流

我们来看下打印结果:

跟我们文档存储的数据是一致的,然后我们再来基于读操作进行写操作

FileOutputStream fos = new FileOutputStream("C:\\Users\\admin\\Desktop\\1.txt")
FileChannel channel1 = fos.getChannel();//另外创一个FileChannel对象跟输出流进行连接
ByteBuffer buffer1 = ByteBuffer.allocate(1024);//同样的开辟1k的缓冲区
while(buff.hasReamining()){
    //这是在之前读操作时,我们来实现读一个,我们写一个
    byte b = buffer.get();
    buffer1.put(b);//我们把当前读到的字节放入我们写数据的缓冲区
}
buffer1.filp();//我们接下来要进行把我们缓冲区的数据写入文档中,所以我们需要先读缓冲区的内容
//所以我们要从写模式转化为读模式
channel1.write(buffer1);//把从缓冲区读到的数据写入我们的channel中,然后就会传给我们的输出流
fos.close();//最后关闭输出流

这样我们的一个基于FileChannel进行的文件拷贝就完成了,我们来看下桌面上的2.txt文件中是否有内容

文件内容与我们给出的文件内容相同 拷贝成功!

基于SocketChannel来完成tcpsocket通信

用完了FileChannel我们再来用socketChannel来进行编程完成客户机与服务器的通信
首先我们先创建一个客户机

SocketChannel socketChannel = SocketChannel.open();//此处跟tcp不一样,但也可以把socketChannel理解为socket
//然后我们要先打开socketChannel
socketChannel.connect(new InetSocketAddress("127.0.0.1",8888));//然后建立跟服务器的连接
//这里的InetSocetAddress跟InetAddress可以理解为一个东西,只不过把地址跟端口号封装在一起
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);//开辟一块为1k的字节写缓存区
String str="我是客户机";
for(int i=0;i<str.length();i++){
    writeBuffer.put(str.getBytes()[i]);//把要传的数据变成字节类型传入写缓存区
}
writeBuffer.flip();//转化为读操作
socketChannel.write(wirteBuffer);//把读到的数据写入Channel内,然后穿给服务器

ByteBuffer readBuffer = ByteBuffer.allocate(1024);//我们开辟一块为1k的字节读缓存区
socketChannel.read(readBuffer);//把从服务端接受的数据写入缓存区中
readBuffer.flip();//改为读模式
byte[] buf =new byte[1024];
while(readBuffer.hasRemaining()){
    byte b = readBuffer.get();
    buf[readBuff.position()-1]=b;//当前的position-1才会是对应的下标
}
String msg = new String(buf);
System.out.println("服务端说"+msg);//打印出服务器传的值

然后我们再来服务器的代码

ServerSocketChannel serverSocketChannel =  ServerSocketChannel.open();
//首先跟客户机一样先打开,ServerSocketChannel跟ServerSocket可以看成一样的
serverSocketChannel.bind(new InetSocketAddress(8888));//绑定端口
SocketChannel socketChannel = serverSocketChannel.accept();//创建SocketChannel对象跟端口建立连接
ByteBuffer readBuffer = ByteBuffer.allocate(1024);//开辟一块1k的字节读缓冲区
ByteBuffer writeBuffer = ByteBuffer.allocate(1024);//开辟一块1k的字节写缓冲区
socketChannel.read(readBuffer);//把缓冲区读到的内容写入Channel内
readBuffer.flip();//将readBuffer改为读模式
byte [] buf = new byte[1024];
while (readBuffer.hasRemaining()){
byte b =readBuffer.get();
buf[readBuffer.position()-1]=b;//当前position-1才是当前下标
}
String msg = new String(buf);
System.out.println("客户端说"+msg);
String str = "我是服务器";
for(int i=0;i<str.length();i++){
writeBuffer.put(str.getBytes()[i]);
}
writeBuffer.flip();
socketChannel.write(writeBuffer);
serverSocketChannel.close();

然后我们这样就完成了一个基于SocketChannel完成的客户机与服务器的通信。
然后本章的内容到此暂时结束,Selector相关内容在《Selector基础》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容

  • JAVA NIO基础 ...
    文思li阅读 607评论 0 3
  • Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java I...
    JackChen1024阅读 7,515评论 1 143
  • 本文大纲如下: 1、什么是NIO 2、为什么使用NIO 3、NIO的基本使用 4、BIO、NIO、AIO区别以及总...
    PuHJ阅读 329评论 0 3
  • (转载说明:本文非原创,转载自http://ifeve.com/java-nio-all/) Java NIO: ...
    数独题阅读 798评论 0 3
  • 约克不常下雪。 圣诞过了,约克没有下雪。元旦过了,约克没有下雪。小寒大寒也过了,冷风呼啸,大地结冰,约克依旧没有下...
    蓝庭芥阅读 2,067评论 33 46