NIO的实战教程(简单且高效)
2023-12-20 16:30:07
1. 参考
建议按顺序阅读以下三篇文章
为什么NIO被称为同步非阻塞?
Java IO 与 NIO:高效的输入输出操作探究
【Java.NIO】Selector,及SelectionKey
2. 实战
我们将模拟一个简单的HTTP服务器,它将响应客户端请求并返回一个固定的响应(”Hello, World!”)。我们将使用IO和NIO两种不同的方式实现此服务器。
2.1 传统阻塞IO
import java.io.*;
public class TraditionalIOExample {
public static void main(String[] args) {
try {
// 打开文件
InputStream input = new FileInputStream("example.txt");
OutputStream output = new FileOutputStream("output.txt");
// 读取和写入数据
int data;
while ((data = input.read()) != -1) {
output.write(data);
}
// 关闭文件
input.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2 非阻塞NIO
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
public class NioHttpServer {
public static void main(String[] args) {
try {
// 创建服务端通道
ServerSocketChannel serverChannel = ServerSocketChannel.open();
// 绑定访问端口
serverChannel.socket().bind(new InetSocketAddress(8080));
// 通道设置为非阻塞
serverChannel.configureBlocking(false);
// 通过open方法创建一个Selector
Selector selector = Selector.open();
/**
必须将channel注册到selector上,并订阅OP_ACCEPT事件
SelectionKey.OP_CONNECT channel成功连接到另一个服务器称为”连接就绪“
SelectionKey.OP_ACCEPT server socket channel准备好接收新进入的连接称为”接收就绪“
SelectionKey.OP_READ 有数据可读的通道可以说是”读就绪“
SelectionKey.OP_WRITE 有数据可写的通道可以说是”读就绪“
*/
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
// 返回你所感兴趣的事件(连接,接受,读或写)已经准备就绪的那些通道
int readyChannels = selector.select();
if (readyChannels == 0){
continue;
}
// 访问”已选择键集“中的就绪通道
Set<SelectionKey> selectedKeys = selector.selectedKeys();
// 可以遍历这个已选择的集合来访问就绪的通道
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
// 注意每次迭代末尾的remove()调用,Selector不会自己从已选择集中移除SelectioKey实例,必须在处理完通道时自己移除。
keyIterator.remove();
// 一个server socket channel准备号接收新进入的连接称为”接收就绪“
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key.channel();
// 客户端socker注册进来
SocketChannel clientChannel = server.accept();
clientChannel.configureBlocking(false);
clientChannel.register(selector, SelectionKey.OP_READ);
// 客户端通道是否有数据流进来
} else if (key.isReadable()) {
SocketChannel clientChannel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
clientChannel.read(buffer);
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
String request = new String(bytes);
String response = "HTTP/1.1 200 OK\r\n\r\nHello, World!\r\n";
ByteBuffer responseBuffer = ByteBuffer.wrap(response.getBytes());
clientChannel.write(responseBuffer);
clientChannel.close();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3. 模型
上述代码结合该模型,第二次阅读代码,会有更深的理解
4. 原理
多路复用才是NIO不阻塞的原因
文章来源:https://blog.csdn.net/m0_46638350/article/details/135009064
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!