常见IO模型(BIO、NIO、AIO)
1.网络模型
- a.编程模型 TCP UDP
- TCP->可靠连接、使命必达、速度慢
- UDP->不可靠、速度快
1.常见的IO模型
- blocking IO == Old IO(BIO)
案例:如果不开线程,那么就会阻塞。
public class Server {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket();
ss.bind(new InetSocketAddress("localhost", 8888));
new Thread(()->{
try {
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println(br.readLine());
br.close();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
});
ss.close();
}
}
- Non-Blocking IO(NIO)->Java的API还不如C
调用Linux底层的epoll(),使用一个Channel,用Selector进行接受
ServerSocket是阻塞式的、Channel是双向的。
模型1
public class Server {
public static void main(String[] args) throws Exception {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress("localhost", 8888));
ssc.configureBlocking(false);
System.out.println("server started, listening on: " + ssc.getLocalAddress());
Selector selector = Selector.open();// selector是个大管家,进行调用epoll
ssc.register(selector, SelectionKey.OP_ACCEPT);// 监听在OP_ACCEPT(连接操作)操作下进行处理
while (true) {
selector.select();// 轮训,无事件发生就进行等待
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> it = keys.iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
it.remove();
handle(key);
}
}
}
private static void handle(SelectionKey key) {
if(key.isAcceptable()) {// 写
try {
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();// 新的通道
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.register(key.selector(), SelectionKey.OP_READ);// 设置为读
} catch (IOException e) {
e.printStackTrace();
}
}else if (key.isReadable()) {// 读
SocketChannel sc = null;
try{
sc = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(512);
buffer.clear();
int len = sc.read(buffer);
if(len != -1) {
System.out.println(new String(buffer.array(), 0, len));
}
ByteBuffer bufferToWrite = ByteBuffer.wrap("HelloClient".getBytes());
sc.write(bufferToWrite);
}catch (IOException e) {
e.printStackTrace();
}finally {
if(sc != null) {
try {
sc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
模型2
这个模型实现起来很难。
重要注意:
1.JDK中ByteBuff中,读写都是一个指针,如果读写操作,必须将其归位。
Netty用ByteBuf中,读写是2个指针。
2.Netty除了ByteBuf,还有ZeroCopy,Netty可以直接操作内存,跨过JVM。
- AIO(Asynchronous IO)
是异步非阻塞型
异步:注册了事件,不去处理,让别人处理