BIO: blocking io
一个线程处理一个客户端连接和读写事件
缺点:效率低,浪费线程资源,一个线程只能处理一个连接
伪代码:
ServerSocket serverSocket = new ServerSocket(8090);
while (true){
Socket clientSocket = serverSocket.accept(); //阻塞,等待客户端连接
Byte[] bytes = new Byte[1024];
int n = clientSocket.getInputStream.read(bytes); //阻塞,等待客户端发送数据
if (n != -1){
System.out.println("收到客户端数据:"+ new String(bytes));
clientSocket.getOutputStream.write("hello client".getBytes());
clientSocket.getOutputStream.flush();
}
}
NIO: nonBlocking io
一个线程处理多个客户端连接和读写事件
简单版本的缺点:会遍历所有连接,每个连接都去读一次数据,如果所有连接中只有少部分发送数据,则大部分遍历是无效的
简单版本伪代码:
List<SocketChannel> channelList = new LinkedList<>();
ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.socket().bind(new InetSocketAddress(8090));
serverSocket.configureBlocking(false); //设置为非阻塞
while (true){
SocketChannel socketChannel = serverSocket.accept(); //不会阻塞,不管有没有客户端连接都会往下执行
while (socketChannel != null){
socketChannel.configureBlocking(false);
channelList.add(socketChannel);
}
Iterator<SocketChannel> iterator = channelList.iterator();
while (iterator.hasNext()){
SocketChannel sc = iterator.next();
ByteBuffer buffer = ByteBuffer.allocate(256);
int n = sc.read(buffer);//不会阻塞,不管客户端又没有发送数据都会往下执行
if (n > 0){
System.out.println(new String(buffer.array()));
} else if(n == -1){//客户端端口,从集合中移出
iterator.remove();
sc.close();
}
}
}
引入多路复用器的版本:
ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.socket().bind(new InetSocketAddress(8090));
serverSocket.configureBlocking(false); //设置为非阻塞
Selector selector = Selector.open();
serverSocket.register(selector,SelectionKey.OP_ACCEPT);
while (true){
selector.select();
Set<SelectionKey> selectionKeys = selector.selectionKeys();
Iterator<SelectionKey> iterator selectionKeys.iterator();
while (iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
if (selectionKey.isAcceptable){//连接事件
ServerSocketChannel serverSocketChannel = (ServerSocketChannel)selectionKey.channel();
SocketChannel socketChannel = serverSocketChannel.accpet();
socketChannel.configureBlocking(false);//设置为非阻塞
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (selectionKey.isReadable){
SocketChannel socketChannel = selectionKey.channel();
ByteBuffer buffer = ByteBuffer.allocate();
int n = socketChannel.read(buffer);
if (n >0){
System.out.println(new String(buffer));
} else if (n == -1){
socketChannel.close();
}
}
}
}