NIO

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.LinkedList;

public class SocketNIO {
    public static void main(String[] args) throws IOException, InterruptedException {
        //selector = Selector.open(); 可以使用这个做多路复用器
        LinkedList clients = new LinkedList<>();//存放曾今连接过的客户端
        ServerSocketChannel ss = ServerSocketChannel.open();//开启监听
        ss.bind(new InetSocketAddress(9090));
        ss.configureBlocking(false);//该步骤能让服务端不用阻塞等待客户端的连接
        while (true) {
            //使当前线程休眠,进入阻塞状态
            Thread.sleep(1000);
            //接受客户端的连接
            SocketChannel client = ss.accept();//在这里并不会阻塞,直接返回了客户端或者null
            if (client != null) {
                client.configureBlocking(false);//设置非阻塞模式。为之后的读取,recv设置非阻塞
                int port = client.socket().getPort();
                System.out.println("client-port:" + port);
                clients.add(client);
            }
            ByteBuffer buffer = ByteBuffer.allocateDirect(4096);
            for (SocketChannel socketChannel : clients) {
                int num = socketChannel.read(buffer);
                if (num > 0) {
                    buffer.flip();
                    byte[] bytes = new byte[buffer.limit()];
                    buffer.get(bytes);
                    String str = new String(bytes);
                    System.out.println(socketChannel.socket().getPort() + ":" + str);
                    buffer.clear();
                }
            }

        }
    }
}
追踪内核调用情况.png

image.png

image.png

image.png

image.png

这个时候,内核提供了个select函数,它能够返回当前连接线程的状态,不需要自己轮询,直接调用select,能收到哪个线程的状态发生了变化,获取到后程序再自己recev那个线程。bio:同步阻塞,因为他有recev,accept。nio同步非阻塞,他返回的客户端没有阻塞。bio,nio属于同步io模型。aio:异步非阻塞,由内核通知主程序带一个buffer过去。自己拉数据叫同步,需要自己recv。被内核推过来数据叫异步。
BIO需要来一个连接就开启一个线程等待接收数据处理。NIO轮询内核,等待内核告诉服务端哪个连接有数据需要处理(返回的是状态,由程序根据状态自己去recv数据)。

你可能感兴趣的:(NIO)