特点:
BIO -- jdk1.0 -- BlockingIO -- 同步阻塞式IO -- 面向流操作字节字符 -- 单向传输 NIO -- jdk1.4 -- NonBlockingIO -- 同步非阻塞式IO -- 面向通道操作缓冲区 -- 双向传输 AIO -- jdk1.7 -- AnsyncronizeIO -- 异步非阻塞式IO -- 大量的使用回调函数实现了异步IO操作开源的NIO结构的服务器框架: MINA NETTY
NIO简单模型图:
1、实现NIO的client端
package nio.dome;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class SocketChannelDemo {
public static void main(String[] args) throws Exception {
// 0.准备选择器
Selector sele = Selector.open();
// 1.创建sc通道对象
SocketChannel sc = SocketChannel.open();
// 2.设置非阻塞模式
sc.configureBlocking(false);
// 3.地址和端口
sc.connect(new InetSocketAddress("127.0.0.1", 44444));
// 4.注册事件
sc.register(sele, SelectionKey.OP_CONNECT);
// 选择和处理
while (true) {
// 执行选择的操作,惟一阻塞方法
sele.select();
Set<SelectionKey> keys = sele.selectedKeys();
if (keys.size() > 0) {
Iterator<SelectionKey> it = keys.iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
if (key.isAcceptable()) {
} else if (key.isConnectable()) {
SocketChannel channel = (SocketChannel) key.channel();
while (!channel.isConnected()) {
channel.finishConnect();
}
// 注册写事件到选择器
channel.register(sele, SelectionKey.OP_WRITE);
} else if (key.isWritable()) {
// 获取write的通道
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buf = ByteBuffer.wrap("hello world ".getBytes());
while (buf.hasRemaining()) {
channel.write(buf);
}
// 注册一个读操作
channel.register(sele, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buf = java.nio.ByteBuffer.allocate(9);
int count = -1;
while ( channel.read(buf) != -1) {
//channel.read(buf);
System.out.println("sjdfs");
}
String str = new String(buf.array());
System.out.println("client: " + str);
// 取消write操作的注册,防止多次write
key.cancel();
} else {
throw new Exception("ni ya! woburenshinia!");
}
}
// 从就绪的键集中删除已经处理的键
it.remove();
}
}
}
}
2、实现NIO的server端
package nio.dome;
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.util.Iterator;
import java.util.Set;
public class ServerSocketChannelDemo {
public static void main(String[] args) throws Exception {
// 0.创建选择器
Selector sele = Selector.open();
//1.创建服务器
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress("127.0.0.1", 44444));
// 2.设置ssc为非阻塞
ssc.configureBlocking(false);
// 3.向选择器中注册ACCEPT操作
ssc.register(sele, SelectionKey.OP_ACCEPT);
//不停的循环选择,不停地处理
while(true) {
//4.选择器进行选择操作
//该方法是NIO中唯一一个阻塞的方法,没有就绪的就阻塞
sele.select();
//5.获取就绪的键
Set<SelectionKey> selectedKeys = sele.selectedKeys();
if(selectedKeys.size() > 0) {
Iterator<SelectionKey> it = selectedKeys.iterator();
//6.遍历就绪的键
while(it.hasNext()) {
SelectionKey key = it.next();
//7.判断当前就绪的键是什么类型的操作
if(key.isAcceptable()) {
ServerSocketChannel channel = (ServerSocketChannel) key.channel();
SocketChannel sc = null;
while(sc == null) {
sc = channel.accept();
}
// 9.为读事件设置非阻塞,将sc注册到选择器中
sc.configureBlocking(false);
sc.register(sele, SelectionKey.OP_READ);
}else if(key.isWritable()) {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buf = ByteBuffer.wrap("hello nio".getBytes());
while(buf.hasRemaining()) {
channel.write(buf);
}
//key.cancel();
}else if(key.isReadable()) {
//8.如果当前是READ操作,则去完成READ操作
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buf = java.nio.ByteBuffer.allocate(11);
while(buf.hasRemaining()) {
sc.read(buf);
}
String str = new String(buf.array());
System.out.println("server: "+str);
//注册写操作
sc.register(sele, SelectionKey.OP_WRITE);
}else {
throw new Exception("ni ya! woburenshinia!");
}
}
//10.删除处理过的就绪的键
it.remove();
}
}
}
}