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,有兴趣的可以研究下怎么解决:
