针对这个话题,我将分几个部分进行详细讲解。
1. 了解Java 网络IO编程
1.1 BIO
BIO即Blocking IO,同步阻塞IO,应用方面比较广泛,缺点是每个客户端连接时都需要创建一个线程,因此比较消耗系统资源,如果客户端连接数比较少,建议使用BIO。
1.2 NIO
NIO即Non-blocking IO,同步非阻塞IO,优点是可以支持多路复用,一个线程可以处理多个客户端连接,缺点是编程复杂,需要熟练掌握Selector、Channel、Buffer等概念。
1.3 AIO
AIO即Asynchronous IO,异步非阻塞IO,通常由操作系统来完成数据传输,Java 7后提供了NIO 2.0,支持异步IO,相较NIO来说,AIO更加简单易用。
2. 示例代码说明
下面我会通过两个具体的示例来说明BIO、NIO、AIO的使用。
2.1 BIO 示例
BIO使用中每个客户端连接时都需要创建一个线程,因此比较消耗系统资源。下面是一个BIO示例代码:
public class BIOServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("Server start at:8888");
while(true){
Socket socket = serverSocket.accept();
Handler handler = new Handler(socket);
new Thread(handler).start();
}
}
static class Handler implements Runnable{
Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
InputStream inputStream = null;
try {
inputStream = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = inputStream.read(bytes)) != -1){
sb.append(new String(bytes,0,len,"UTF-8"));
}
System.out.println("Server receive message:" + sb);
} catch (IOException e) {
e.printStackTrace();
} finally {
if(inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
2.2 NIO 示例
NIO使用中可以一个线程处理多个客户端连接,相较BIO来说,可以更加节省系统资源。下面是一个NIO示例代码:
public class NIOServer {
public static void main(String[] args) throws IOException {
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress(8888));
Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
int readyChannels = selector.select();
if (readyChannels == 0) continue;
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key.isAcceptable()) {
ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
SocketChannel channel = serverChannel.accept();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
System.out.println("客户端连接成功,IP地址为:" + channel.getRemoteAddress());
} else if (key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int read = channel.read(buffer);
if (read > 0) {
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
String message = new String(bytes, "UTF-8");
System.out.println("Server receive message:" + message);
} else if (read < 0) {
key.cancel();
channel.close();
}
}
keyIterator.remove();
}
}
}
}
2.3 AIO 示例
AIO使用中相较NIO来说更加简单易用,Java 7以后提供了NIO 2.0支持异步IO。下面是一个AIO示例代码:
public class AIOEchoServer {
private AsynchronousServerSocketChannel serverSocketChannel;
public AIOEchoServer(int port) throws Exception {
serverSocketChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(port));
}
public void start() {
serverSocketChannel.accept(this, new CompletionHandler<AsynchronousSocketChannel, AIOEchoServer>() {
ByteBuffer buffer = ByteBuffer.allocate(1024);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
@Override
public void completed(AsynchronousSocketChannel channel, AIOEchoServer attachment) {
buffer.clear();
baos.reset();
try {
channel.read(buffer).get();
buffer.flip();
baos.write(buffer.array(), 0, buffer.remaining());
String message = new String(baos.toByteArray(), "UTF-8");
System.out.println("Server receive message:" + message);
buffer.clear();
channel.write(ByteBuffer.wrap(("Echo:" + message).getBytes("UTF-8"))).get();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void failed(Throwable exc, AIOEchoServer attachment) {
exc.printStackTrace();
}
});
System.out.println("Server start at:8888");
}
public static void main(String[] args) throws Exception {
new AIOEchoServer(8888).start();
Thread.sleep(100000);
}
}
在这里,通过以上三个示例,可以很好地了解BIO、NIO、AIO这三种不同网络IO编程模型的使用方式。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码) - Python技术站