一、IO是什么?
IO 全称:input/output 输入/输出
那么IO就是用来传输数据的!!!
那什么是流?
流,是一个抽象的东西。是一连串连续动态的数据集合
那什么是输入流?什么是输出流?
首先你要明白一件事,输入流和输出流的中心是程序!
例如: 读和写,都是以人的大脑为中心,读书是把书上的信息读进大脑,写字是把大脑里的信息写在纸上。
那么输入流就是把数据–>程序,输出流就是把程序–>目的地
向本地文件写数据用输出流,读取本地文件数据用输入流,输入输出是相对于程序来说的。
所以就有下面这个图,当你上传文件的时候,你本地就是数据源,服务器就是目的地。当你下载文件的时候,服务器就是数据源,本地就是目的地。
1.1 这里补充一下什么是BIO
Java BIO (blocking I/O): 同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
那么IO就是阻塞的
这里有两个概念
什么是同步:大家都去银行取过钱对吧,每个人都是独立的,有人开车过去取钱,有人走路,每个人对于银行营业厅来说就是同步的,你们可以一起取钱嘛,互不干扰。再打个必然,你一边蹲坑一边玩手机,玩手机和蹲坑互不干扰,各干各的,没有谁规定说你蹲坑的时候一定要看抖音不能看电影吧?
什么是阻塞呢: 大家在公共厕所上过厕所吧? 尤其是火车站啊、地铁站啊,这些人多的地方。人多就算了,关键坑位还少。有很多人排队,那你想上厕所就肯定要等里面的人多来吧?这就是阻塞。
听明白没?没明白再给你们准备一张图:
有八个人排队上公共厕所,公共厕所只有四个坑位,1、2、3、4这四个人相对来说就是同步的,因为他们等的不是用一个坑位彼此互补影响,1、5 两个人就是阻塞的,因为5要等1上完了,才轮到他!!!
二、流的分类
按方向来划分: 输入流和输出流
按功能来划分: 节点流和处理流(包装流)
按数据来划分: 字节流和字符流
三、NIO是什么?
NIO (new IO)
四、NIO和IO的区别
下面一张图看看NIO是什么,比如:你在南京想去北京玩,那么你可以做高铁去北京,高铁轨道就是通道,缓冲区就是高铁,数据就是乘客。
4.1 缓冲区(Buffer)
缓冲区(Buffer): 在Java NIO 中负责数据的存取。缓冲区就数组。用于存储不同数据类型
根据数据类型不同(Boolean 除外),提供相应类型的缓冲区:
- ByteBuffer
- CharBuffer
- ShortBuffer
- IntBuffer
- LongBuffer
- FoaltBuffer
- DoubleBuffer
上述缓冲区的管理方式几乎一致,通过 allocate() 获取缓冲区
缓冲区获取数据的两个核心的方法:
- put(): 存入数据到缓冲区
- get(): 从缓冲区获取数据
缓冲区中的四个核心的属性:
- capacity: 容量, 表示缓冲区中最大存储的容量。一旦声明,不可改变。
- limit: 界限, 表示缓冲区中可以操作数据的大小。(limit 后面的数据不能进行读写)
- position: 位置, 表示缓冲区中正在操作数据的位置。
- mark: 标记, 表示记录当前position的位置。可以通过 reset() 恢复到 mark 的位置。
0 <= mark <= position <= limit <= capacity
代码部分:
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import java.nio.ByteBuffer;
/**
*
* 一、缓冲区(Buffer): 在Java NIO 中负责数据的存取。缓冲区就数组。用于存储不同数据类型
*
*根据数据类型不同(Boolean 除外),提供相应类型的缓冲区:
* ByteBuffer
* CharBuffer
* ShortBuffer
* IntBuffer
* LongBuffer
* FoaltBuffer
* DoubleBuffer
*
* 上述缓冲区的管理方式几乎一致,通过 allocate() 获取缓冲区
*
* 二、缓冲区获取数据的两个核心的方法:
* put(): 存入数据到缓冲区
* get(): 从缓冲区获取数据
*
* 三、缓冲区中的四个核心的属性:
* capacity: 容量, 表示缓冲区中最大存储的容量。一旦声明,不可改变。
* limit: 界限, 表示缓冲区中可以操作数据的大小。(limit 后面的数据不能进行读写)
* position: 位置, 表示缓冲区中正在操作数据的位置。
* mark: 标记, 表示记录当前position的位置。可以通过 reset() 恢复到 mark 的位置。
*
* 0 <= mark <= position <= limit <= capacity
*
* @author yangjikang
* @date 2019/7/9 16:30
* @modified By yangjikang
*/
public class demo01 {
public static void main(String[] args) {
String s = "abcdef";
//1.分配一个指定大小的缓冲区
ByteBuffer buf = ByteBuffer.allocate(10);
System.out.println("==================allocate====================");
System.out.println(buf.position());
System.out.println(buf.limit());
System.out.println(buf.capacity());
//2.利用put()存入数据到缓冲区
buf.put(s.getBytes());
System.out.println("==================put()====================");
System.out.println(buf.position());
System.out.println(buf.limit());
System.out.println(buf.capacity());
//3.切换读取数据模式
buf.flip();
System.out.println("==================flip()====================");
System.out.println(buf.position());
System.out.println(buf.limit());
System.out.println(buf.capacity());
//4.利用get()方法读取缓冲区中的数据
byte[] temp = new byte[buf.limit()];
buf.get(temp);
System.out.println("==================get()====================");
System.out.println(new String(temp,0,temp.length));
System.out.println(buf.position());
System.out.println(buf.limit());
System.out.println(buf.capacity());
//5.rewind() : 可重复读
buf.rewind();
System.out.println("==================rewind()====================");
System.out.println(buf.position());
System.out.println(buf.limit());
System.out.println(buf.capacity());
//6.clear() : 清空缓冲区,但是缓冲区里的数据还存在,只是处于“被遗忘”状态
buf.clear();
System.out.println("==================clear()====================");
System.out.println(buf.position());
System.out.println(buf.limit());
System.out.println(buf.capacity());
System.out.println((char) buf.get());
}
}
控制台:
flip()反转,将指针重置回开始。
mark 和 reset
代码部分:
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import java.nio.ByteBuffer;
/**
* mark: 标记, 表示记录当前position的位置。可以通过 reset() 恢复到 mark 的位置。
*
* @author yangjikang
* @date 2019/7/10 9:58
* @modified By yangjikang
*/
public class demo02 {
public static void main(String[] args) {
String str = "1234567";
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put(str.getBytes());
buffer.flip();
//创建临时接收缓冲区数据的数组
byte[] temp = new byte[buffer.limit()];
//读取三个字符到temp从0号下标开始放
buffer.get(temp, 0, 3);
System.out.println("第一次读取内容: " + new String(temp, 0, temp.length));
System.out.println("第一次读取后的position位置: " + buffer.position());
//标记当前position位置
buffer.mark();
//读取两个字符到temp从1号下标开始放
buffer.get(temp, 1, 2);
System.out.println("第二次读取内容: " + new String(temp, 0, temp.length));
System.out.println("第二次读取后的position位置: " + buffer.position());
//通过reset恢复到mark位置
buffer.reset();
System.out.println("通过reset恢复后的position位置: " + buffer.position());
}
}
控制台:
五、NIO的直接缓冲区和非直接缓冲区
非直接缓冲区: 通过allocate() 方法分配缓冲区,将缓冲区建立在JVM内存上。
直接缓冲区: 通过allocateDirect() 方法分配直接内存,将缓冲区建立在物理内存中。
看图
代码:
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* 一、通道(Channel): 用于源节点和目标节点的连接。在Java NIO中负责缓冲区中数据的传输。Channel本身不存储数据,
* 需要配合缓冲区(Buffer)进行数据的传输
* <p>
* 二、通道的主要是实现类
* java.nio.channels.channel 接口:
* |--FileChannel
* |--SocketChannel
* |--ServerSocketChannel
* |--DatagramChannel
* <p>
* 三、获取通道
* 1.Java 针对支持通道的类提供了 getChannel()方法
* 本地IO:
* FileInputStream/FileOutputStream
* RandomAccessFile
* <p>
* 网络IO:
* Socket
* ServerSocket
* Datagram
* <p>
* 2.在JDK1.7中的NIO.2针对各个通道提供了静态方法open()
* 3.在JDK1.7中的NIO.2的Files 工具类 newByteChannel()
*
* @author yangjikang
* @date 2019/7/10 13:47
* @modified By yangjikang
*/
public class demo03 {
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
FileChannel inChannel = null;
FileChannel outChannel = null;
int count = 0;
try {
fileInputStream = new FileInputStream("1.jpg");
fileOutputStream = new FileOutputStream("2.jpg");
//step.1 获取通道
inChannel = fileInputStream.getChannel();
outChannel = fileOutputStream.getChannel();
//step.2 分配指定大小的缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//step.3 将通道中数据放入缓冲区中
while (inChannel.read(byteBuffer) != -1) {
byteBuffer.flip();//切换读模式
//step.4 将缓冲区中的数据读入通道中
outChannel.write(byteBuffer);
byteBuffer.clear();//清空当前缓冲区
count++;
}
System.out.println(count);
System.out.println(inChannel);
System.out.println(outChannel);
System.out.println(fileInputStream);
System.out.println(fileOutputStream);
} catch (Exception e) {
e.printStackTrace();
} finally {
inChannel.close();
outChannel.close();
fileInputStream.close();
fileOutputStream.close();
}
}
}
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
/**
* @author yangjikang
* @date 2019/7/10 14:16
* @modified By yangjikang
*/
public class demo04 {
public static void main(String[] args) throws IOException {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
//使用直接缓冲区完成文件的复制(内存映射文件)
inputChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
outputChannel = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
//内存映射文件
MappedByteBuffer inputMap = inputChannel.map(FileChannel.MapMode.READ_ONLY, 0, inputChannel.size());
MappedByteBuffer outputMap = outputChannel.map(FileChannel.MapMode.READ_WRITE, 0, inputChannel.size());
//直接对缓冲区进行数据的读写操作
byte[] bytes = new byte[inputMap.limit()];
inputMap.get(bytes);
outputMap.put(bytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
inputChannel.close();
outputChannel.close();
}
}
}
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
/**
*
* 四、通道直接的数据传输
* transferTo()
* transferFrom()
*
* @author yangjikang
* @date 2019/7/10 14:37
* @modified By yangjikang
*/
public class demo05 {
public static void main(String[] args) throws IOException {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
//使用直接缓冲区完成文件的复制(内存映射文件)
inputChannel = FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
outputChannel = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
// inputChannel.transferTo(0, inputChannel.size(), outputChannel);
outputChannel.transferFrom(inputChannel,0,inputChannel.size());
}catch (Exception e){
e.printStackTrace();
}finally {
inputChannel.close();
outputChannel.close();
}
}
}
六、分散读取和聚集写入
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* 五、分散(Scatter)和聚集(Gather)
* 分散读取(Scattering Reads): 将通道中的数据分散到多个缓冲区中
* 聚集写入(Gathering Writes): 将多个缓冲区中的数据聚集到通道中
*
* @author yangjikang
* @date 2019/7/10 14:53
* @modified By yangjikang
*/
public class demo06 {
public static void main(String[] args) throws IOException {
RandomAccessFile read = new RandomAccessFile("1.txt", "rw");
//step.1 获取通道
FileChannel channel = read.getChannel();
//step.2 分配指定大小的缓冲区
ByteBuffer allocate1 = ByteBuffer.allocate(50);
ByteBuffer allocate2 = ByteBuffer.allocate(100);
//step.3 分散读取数据到多个缓冲区
ByteBuffer[] byteBuffers = {allocate1, allocate2};
channel.read(byteBuffers);
for (ByteBuffer byteBuffer : byteBuffers) {
byteBuffer.flip();
}
//step.4 打印结果
System.out.println(new String(byteBuffers[0].array(), 0, byteBuffers[0].limit()));
System.out.println("========================================");
System.out.println(new String(byteBuffers[1].array(), 0, byteBuffers[1].limit()));
//聚集写入
RandomAccessFile write = new RandomAccessFile("3.txt", "rw");
FileChannel writeChannel = write.getChannel();
writeChannel.write(byteBuffers);
}
}
七、字符集
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
/**
* 六、字符集:Charset
* 编码:字符串 --> 字节数组
* 解码:字节数组 --> 字符串
*
* @author yangjikang
* @date 2019/7/10 15:57
* @modified By yangjikang
*/
public class demo07 {
public static void main(String[] args) throws CharacterCodingException {
//查看字符集有哪些
SortedMap<String, Charset> stringCharsetSortedMap = Charset.availableCharsets();
Set<Map.Entry<String, Charset>> entries = stringCharsetSortedMap.entrySet();
for (Map.Entry<String, Charset> entry : entries) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
//指定编码方式
Charset gbk = Charset.forName("GBK");
//获取编码器
CharsetEncoder charsetEncoder = gbk.newEncoder();
//获取解码器
CharsetDecoder charsetDecoder = gbk.newDecoder();
//创建字符缓冲区
CharBuffer allocate = CharBuffer.allocate(1024);
allocate.put("yangjikang");
allocate.flip();
//编码
ByteBuffer encode = charsetEncoder.encode(allocate);
for (int i = 0; i < encode.limit(); i++) {
System.out.println(encode.get());
}
//解码
encode.flip();
CharBuffer decode = charsetDecoder.decode(encode);
System.out.println(decode);
}
}
八、IO阻塞和NIO非阻塞
read(缓冲区) --> 上车 :可以理解为把 数据源 通道(channel)里面的数据读取到缓冲区(buffer)
write(缓冲区) --> 下车 :可以理解为把缓冲区(buffer)里面的数据读取到 目的地 通道(channel)
8.1阻塞网络通信
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import org.junit.Test;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
/**
* 阻塞和非阻塞
*
* 一、使用NIO完成网路通信的三个核心:
* 1.通道:负责连接
* java.nio.channels.channel 接口:
* |-- SelectableChannel
* |-- SocketChannel
* |-- ServerSocketChannel
* |-- DatagramChannel
*
* |-- Pipe.SinkChannel
* |-- Pipe.SourceChannel
*
* 2.缓冲区:负责数据存储
*
* 3.选择器: 是 SelectableChannel的多路复用器。用于监听SelectableChannel的IO状况。
*
* @author yangjikang
* @date 2019/7/10 16:36
* @modified By yangjikang
*/
public class demo08 {
@Test
public void Client() throws IOException {
//获取通道
SocketChannel open = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8989));
RandomAccessFile read = new RandomAccessFile("1.jpg", "rw");
FileChannel channel = read.getChannel();
//分配指定大小的缓冲区
ByteBuffer allocate = ByteBuffer.allocate(1024);
//读取本地文件,并发送到服务器
while(channel.read(allocate) != -1){
allocate.flip();
open.write(allocate);
allocate.clear();
}
read.close();
open.close();
}
@Test
public void Server() throws IOException {
//获取通道
ServerSocketChannel open = ServerSocketChannel.open();
RandomAccessFile read = new RandomAccessFile("15.jpg", "rw");
FileChannel channel = read.getChannel();
//绑定连接
open.bind(new InetSocketAddress(8989));
//获取客服端连接的通道
SocketChannel accept = open.accept();
//分配一个指定大小的缓冲区
ByteBuffer allocate = ByteBuffer.allocate(1024);
//接受客服端的数据保存到本地
while(accept.read(allocate) != -1){
allocate.flip();
channel.write(allocate);
allocate.clear();
}
//关闭通道
channel.close();
open.close();
}
}
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import org.junit.Test;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.TimeUnit;
/**
* 阻塞NIO
*
* @author yangjikang
* @date 2019/7/10 17:56
* @modified By yangjikang
*/
public class demo09 {
@Test
public void Client() throws IOException, InterruptedException {
//获取通道
SocketChannel open = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8989));
RandomAccessFile read = new RandomAccessFile("1.jpg", "rw");
FileChannel channel = read.getChannel();
//分配指定大小的缓冲区
ByteBuffer allocate = ByteBuffer.allocate(1024);
//读取本地文件,并发送到服务器
while (channel.read(allocate) != -1) {
allocate.flip();
open.write(allocate);
allocate.clear();
}
open.shutdownOutput();
//接收服务端的反馈
int len;
while ((len = open.read(allocate)) != -1) {
System.out.println("接收服务端反馈");
allocate.flip();
System.out.println(new String(allocate.array(), 0, len));
allocate.clear();
}
read.close();
open.close();
}
@Test
public void Server() throws IOException {
//获取通道
ServerSocketChannel open = ServerSocketChannel.open();
RandomAccessFile read = new RandomAccessFile("18.jpg", "rw");
FileChannel channel = read.getChannel();
//绑定连接
open.bind(new InetSocketAddress(8989));
//获取客服端连接的通道
SocketChannel accept = open.accept();
//分配一个指定大小的缓冲区
ByteBuffer allocate = ByteBuffer.allocate(1024);
//接受客服端的数据保存到本地
while (accept.read(allocate) != -1) {
allocate.flip();
channel.write(allocate);
allocate.clear();
}
allocate.put("服务端接收数据成功!".getBytes());
allocate.flip();
accept.write(allocate);
accept.shutdownOutput();
//关闭通道
channel.close();
accept.close();
open.close();
}
}
8.2非阻塞网络通信
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import org.junit.Test;
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.file.Paths;
import java.util.Iterator;
/**
* 阻塞和非阻塞
*
* 一、使用NIO完成网路通信的三个核心:
* 1.通道:负责连接
* java.nio.channels.channel 接口:
* |-- SelectableChannel
* |-- SocketChannel
* |-- ServerSocketChannel
* |-- DatagramChannel
*
* |-- Pipe.SinkChannel
* |-- Pipe.SourceChannel
*
* 2.缓冲区:负责数据存储
*
* 3.选择器: 是 SelectableChannel的多路复用器。用于监听SelectableChannel的IO状况。
*
* @author yangjikang
* @date 2019/7/10 16:36
* @modified By yangjikang
*/
public class demo10 {
//客户端
@Test
public void client() throws IOException {
//获取通道
SocketChannel open = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8899));
//切换成非阻塞模式
open.configureBlocking(false);
//分配指定大小的缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//发送数据给服务端
byteBuffer.put("来自客户端的一条数据".getBytes());
byteBuffer.flip();
open.write(byteBuffer);
byteBuffer.clear();
//关闭通道
open.close();
}
//服务端
@Test
public void server() throws IOException {
//获取通道
ServerSocketChannel open = ServerSocketChannel.open();
//切换非阻塞模式
open.configureBlocking(false);
//绑定连接
open.bind(new InetSocketAddress(8899));
//获取选择器
Selector selector = Selector.open();
//将通道注册到选择器上,并且指定”监听接收事件“
open.register(selector, SelectionKey.OP_ACCEPT);
//轮询获取选择器上已经准备就绪的事件
while (selector.select() > 0){
//获取当前选择器所有已经准备就绪的事件key
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()){
//获取准备就绪的事件
SelectionKey next = iterator.next();
//判断具体是什么事件
if(next.isAcceptable()){//接收事件
//获取客户端连接
SocketChannel acceptChannel = open.accept();
//切换非阻塞模式
acceptChannel.configureBlocking(false);
//将通道注册到选择器上
acceptChannel.register(selector,SelectionKey.OP_READ);
}else if(next.isReadable()){//读取事件
//获取选择器上”读就绪“状态的通道
SocketChannel readChannel = (SocketChannel)next.channel();
//读取数据
ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //创建一个指定大小的缓冲器
while (readChannel.read(byteBuffer) != -1 ){
byteBuffer.flip();
System.out.println(new String(byteBuffer.array(),0,byteBuffer.limit()));
byteBuffer.clear();
}
}
//取消选择键(SelectionKey)
iterator.remove();
}
}
}
}
8.3非阻塞数据包(DatagramChannel)通道
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import org.junit.Test;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
/**
* @author yangjikang
* @date 2019/7/11 11:43
* @modified By yangjikang
*/
public class demo11 {
@Test
public void send() throws IOException {
DatagramChannel dc = DatagramChannel.open();
dc.configureBlocking(false);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
byteBuffer.put(("来自send的数据:你好").getBytes());
byteBuffer.flip();
dc.send(byteBuffer, new InetSocketAddress("127.0.0.1", 8899));
byteBuffer.clear();
dc.close();
}
@Test
public void receive() throws IOException {
DatagramChannel dc = DatagramChannel.open();
dc.configureBlocking(false);
dc.bind(new InetSocketAddress(8899));
Selector selector = Selector.open();
dc.register(selector, SelectionKey.OP_READ);
while (selector.select() > 0) {
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey next = iterator.next();
if (next.isReadable()) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
dc.receive(byteBuffer);
byteBuffer.flip();
System.out.println(new String(byteBuffer.array(), 0, byteBuffer.limit()));
byteBuffer.clear();
}
}
iterator.remove();
}
}
}
8.4 单向管道(Pipe)
/*
* Copyright (C), 2013-2019, 天津大海云科技有限公司
*/
package nio;
import org.junit.Test;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Pipe;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
/**
* 3
*
* @author yangjikang
* @date 2019/7/11 11:58
* @modified By yangjikang
*/
public class demo12 {
@Test
public void pipe() throws IOException {
//获取管道
Pipe pipe = Pipe.open();
//将缓冲区的数据写入管道
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
Pipe.SinkChannel sink = pipe.sink();
byteBuffer.put("向单向管道发送数据".getBytes());
byteBuffer.flip();
sink.write(byteBuffer);
//读取缓冲区里面的数据
Pipe.SourceChannel source = pipe.source();
//创建一个缓冲区用来接收数据
ByteBuffer accpetByteBuffer = ByteBuffer.allocate(1024);
byteBuffer.flip();
source.read(accpetByteBuffer);
System.out.println(new String(accpetByteBuffer.array(),0,accpetByteBuffer.limit()));
}
}