BIO:Non-Block Input Output 非阻塞式的輸入和輸出,面向緩沖區的。示例代碼如下:
1、服務端Server
package com.example.nio.server;
import java.io.IOException;
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 NioServer {
private static int port = 8080;
private static Selector selector;
private static ByteBuffer buffer = ByteBuffer.allocate(1024);
static{
try {
//擷取channel通道
ServerSocketChannel server = ServerSocketChannel.open();
//設定為非阻塞
server.configureBlocking(false);
//建立連接配接
InetSocketAddress address = new InetSocketAddress(port);
server.bind(address);
//擷取選擇器,用于輪詢
selector = Selector.open();
//使用給定的選擇器注冊此通道
server.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("BioServer 已經啟動,監聽端口是:"+port);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start (){
try {
//開始進行輪詢
while(true){
//檢查其相應的通道有沒有已準備好進行I/O
int count = selector.select();
if(count == 0){
continue;
}
//擷取輪詢的key,并逐個對其進行處理
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> i = keys.iterator();
while(i.hasNext()){
SelectionKey key = i.next();
//對每一個key進行處理
process(key);
i.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void process(SelectionKey key) throws IOException {
//讀寫資料
if(key.isAcceptable()){
ServerSocketChannel setver = (ServerSocketChannel)key.channel();
SocketChannel client = setver.accept();
client.configureBlocking(false);
client.register(this.selector,SelectionKey.OP_READ);
}else if(key.isReadable()){
SocketChannel client = (SocketChannel)key.channel();
int len = client.read(this.buffer);
if(len > 0){
buffer.flip();
String message = new String(buffer.array(),0,len);
client.register(selector,SelectionKey.OP_WRITE, message);
}
buffer.clear();
}else if(key.isWritable()){
SocketChannel client = (SocketChannel)key.channel();
String message = (String)key.attachment();
System.out.println("服務端接收到的資訊為:"+ message);
client.write(ByteBuffer.wrap(("Clint Say:"+ message).getBytes()));
client.close();
}
}
public static void main(String[] args) {
//NIO代碼
new NioServer().start();
}
}
2、用戶端Client
package com.example.nio.client;
import java.io.*;
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.Scanner;
import java.util.Set;
public class NioClient {
private static Selector selector;
private static SocketChannel socketChannel;
static {
try {
//擷取channel通道
socketChannel = SocketChannel.open();
//設定為非阻塞
socketChannel.configureBlocking(false);
//建立連接配接
socketChannel.connect(new InetSocketAddress("localhost",8080));
//擷取選擇器,用于輪詢
selector = Selector.open();
//使用給定的選擇器注冊此通道
socketChannel.register(selector, SelectionKey.OP_READ);
while (!socketChannel.finishConnect()){
System.out.println("重新連接配接......");
}
System.out.println("用戶端已連接配接到服務端......");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//NIO
try {
//設定緩沖區
ByteBuffer buffer = ByteBuffer.allocate(1024);
new clientThread(selector, socketChannel).start();
while(true){
System.out.println("send:");
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
buffer.put(name.getBytes());
buffer.flip();
socketChannel.write(buffer);
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
static class clientThread extends Thread{
private Selector selector;
private SocketChannel socketChannel;
public clientThread(Selector selector, SocketChannel socketChannel) {
this.selector = selector;
this.socketChannel = socketChannel;
}
public void run(){
try {
//讀寫資料
while (true){
int count = selector.select();
if(count == 0){
continue;
}
//擷取輪詢的key,并逐個對其進行處理
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> i = keys.iterator();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while(i.hasNext()){
SelectionKey key = i.next();
if(key.isValid()){
if(key.isReadable()){
SocketChannel socketChannel = (SocketChannel)key.channel();
socketChannel.read(byteBuffer);
byteBuffer.flip();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
System.out.println("讀取到的資訊為:"+ new String(bytes));
byteBuffer.clear();
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
最後給出運作結果截圖,這個示例稍微有點bug,有興趣的可以研究下怎麼解決:
