详解Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

针对这个话题,我将分几个部分进行详细讲解。

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技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • Java基础教程之八大基本数据类型

    Java基础教程之八大基本数据类型 在Java中,基本数据类型指的是不同类型的数据的原始值,它们是Java程序设计的基础。Java中有八种基本数据类型,分别是: byte:8位有符号整数,取值范围为-128到127; short:16位有符号整数,取值范围为-32768到32767; int:32位有符号整数,取值范围为-2147483648到2147483…

    Java 2023年5月26日
    00
  • java Zookeeper简述

    下面是关于“Java Zookeeper简述”的完整攻略。 Zookeeper是一个分布式应用程序协调服务,用于在分布式系统中管理和协调各种服务,如Hadoop、Storm、Kafka等。其中,Zookeeper通过提供一些基本服务将这些服务组合成更高级别的服务,例如Leader Election、Configuration Management等,以简化分…

    Java 2023年5月24日
    00
  • 全面解析JTA 深度历险

    全面解析JTA 深度历险攻略 前言 JTA(Java Transaction API)是Java EE平台中用于处理分布式事务的标准API。本攻略旨在深度解析JTA的基本概念、API和应用场景,让读者能够深入理解JTA并能够在实际开发中应用JTA处理分布式事务。 JTA基础概念 事务 事务是指一系列数据库操作的逻辑单元,通常是由一份或多份数据库操作组成的序列…

    Java 2023年5月20日
    00
  • 详解spring整合shiro权限管理与数据库设计

    详解Spring整合Shiro权限管理与数据库设计 引言 本文详细讲解如何使用Spring框架整合Shiro权限管理,并给出完整的数据库设计方案和示例代码。 Shiro简介 Shiro是一个强大的Java安全框架,可以提供身份认证、授权、加密等各种安全相关的功能。Shiro使用非常简单,易于集成到Java应用中。 Spring整合Shiro权限管理 引入Sh…

    Java 2023年5月20日
    00
  • android中Fragment+RadioButton实现底部导航栏

    底部导航栏在Android应用中非常常见,利用Fragment+RadioButton可以轻松实现这个效果。下面是详细的步骤: 1. 布局文件 首先,在主布局文件中添加FrameLayout来放置Fragment。 <FrameLayout android:id="@+id/container" android:layout_wid…

    Java 2023年5月30日
    00
  • spring注解@Service注解的使用解析

    现在我就为你详细讲解使用Spring中的@Service注解的完整攻略。 什么是@Service注解 在Spring中,@Service注解用来标注业务层(Service层)组件,将业务逻辑封装在Service层,通过@Service注解告诉Spring容器需要将这个类识别为Service层的组件,从而进行自动注入和管理。与@Controller注解和@Re…

    Java 2023年5月31日
    00
  • Java 动态模拟操作系统进程调度算法

    Java 动态模拟操作系统进程调度算法攻略 简介 在操作系统中,进程调度算法是非常重要的一个部分。操作系统需要根据不同的算法,按照一定的规则来决定哪个进程应该被执行。一种常见的调度算法是进程优先级调度算法。本攻略将演示如何使用Java语言动态模拟进程优先级调度算法。 实现 首先,定义一个Process类,代表一个进程,其中包含三个成员变量:进程名、进程优先级…

    Java 2023年5月19日
    00
  • JAVA位运算的知识点总结

    JAVA位运算的知识点总结 什么是位运算 在计算机中,数据都是以二进制表示的。位运算就是直接对二进制的位进行操作的运算,包括位与、位或、位异或以及位移动等操作。 位运算符号 位运算符号包括: 按位与:& 按位或:| 按位异或:^ 左移运算:<< 右移运算:>> 无符号右移运算:>>> 下面对每种符号进行详细讲…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部