Java 的 BIO和NIO简介及聊天室Demo

java有三钟io模型:分别是BIO,NIO,AIO,

BIO

BIO: 同步阻塞型io. 传统的Socket编程即BIO, 一个连接需要一个线程处理.
在这里插入图片描述

基于BIO即 Socket实现的聊天demo
代码示例:

服务端:

package com.czy.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * BIO客户端,
 * 支持多线程连接一个线程处理一个请求
 */
public class ServerDemo {

    public static void main(String[] args) throws IOException {
        //1.创建线程池
        ExecutorService executorService = Executors.newCachedThreadPool();
        //2.服务端创建ServerSocket 对象 绑定服务端监听端口
        ServerSocket serverSocket = new ServerSocket(9090);
        while (true){
            //3. 服务端 阻塞监听socket连接
            Socket socket = serverSocket.accept();
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    //4. 业务处理读取和写入数据
                    handle(socket);
                }
            });
        }
    }


    private static void handle(Socket socket){
        try {
            InputStream inputStream = socket.getInputStream();
            byte[] bytes = new byte[1024];
            int read = inputStream.read(bytes);
            System.out.println("客户端:"+new String(bytes,0,read,StandardCharsets.UTF_8));
            Scanner scanner = new Scanner(System.in);
            String s = scanner.nextLine();
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write(s.getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

客户端:

package com.czy.client;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/**
 * 客户端
 *
 */
public class ClientDemo {

    public static void main(String[] args) throws IOException {
        while (true){
            //1.创建Socket对象  绑定主机和端口,
            Socket socket = new Socket("127.0.0.1",9090);

            //2.创建输出流,便于后续socket向客户端发送数据
            OutputStream outputStream = socket.getOutputStream();
            Scanner scanner = new Scanner(System.in);
            String s = scanner.nextLine();

            // 3.向输出流中写入数据
            outputStream.write(s.getBytes(StandardCharsets.UTF_8));

            // 4.读取服务端发送的数据
            InputStream inputStream = socket.getInputStream();
            byte[] bytes = new byte[1024];
            int read = inputStream.read(bytes);
            System.out.println("服务端:"+new String(bytes,0,read,StandardCharsets.UTF_8));

            // 5.关闭流
            socket.close();
        }
    }
}

NIO

NIO简介:

同步非阻塞型io,一个线程处理多个连接请求,客户端发送的连接请求会注册到多路复用器上,多路复用器轮询到有IO请求的连接就进行处理
在这里插入图片描述

NIO三大核心概念的关系:

下图描述了NIO的Selector(选择器),Channel(通道)和Buffer(缓存区)的关系

1.一个客户端连接一个Channel,对应一个Buffer,
2.每条Channel都会注册到Selector上,Selector轮询Channel上事件,Selector根据不同的事件处理
3.Buffer本质上是数组,不同与BIO的是BIO只能读或者只能写,NIO的buffer是双向的,可读可写.

代码示例:基于NIO实现的聊天Demo: 该demo是未加Selector的编程的.有点繁杂,感兴趣的可以自行百度

客户端:

public class NIOClient {

    public static void main(String[] args) throws IOException {
        //1.打开通道
        SocketChannel socketChannel = SocketChannel.open();
        //2.绑定对应的端口
        socketChannel.connect(new InetSocketAddress("127.0.0.1",9999));
        //3.向缓冲区中写入数据
        socketChannel.write(ByteBuffer.wrap("老板,还钱吧".getBytes(StandardCharsets.UTF_8)));

        //4.申请缓冲区读取服务端信息
        ByteBuffer allocate = ByteBuffer.allocate(1024);
        int read = socketChannel.read(allocate);
        System.out.println("服务端消息:"+new String(allocate.array(),0,read,StandardCharsets.UTF_8));
        socketChannel.close();
    }
}

服务端:


public class NIOServer {
    public static void main(String[] args) throws IOException, InterruptedException {

        //1.打开服务端通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        //2.绑定对应的端口号
        serverSocketChannel.bind(new InetSocketAddress(9999));

        //3.通道默认是阻塞的,需要设置成非阻塞
        serverSocketChannel.configureBlocking(false);

        System.out.println("服务端启动成功...");

        while (true){
            //4.检查是否有客户端连接, 有客户端连接会返回对应的通道
            SocketChannel socketChannel = serverSocketChannel.accept();
            if (socketChannel == null){
                System.out.println("没有客户端连接...");
                Thread.sleep(3000);
                continue;
            }
            //5.获取客户端传递过来的数据,并将数据发在缓冲区中
            ByteBuffer allocate = ByteBuffer.allocate(1024);
            //返回值:正数本地没有读到有效字节数
            //0:表示本地没有读到数据
            //-1表示读到末尾
            int read = socketChannel.read(allocate);
            System.out.println("客户端消息: "+new String(allocate.array(),0,read, StandardCharsets.UTF_8));
            //6.向客户端返会数据
            socketChannel.write(ByteBuffer.wrap("没钱".getBytes(StandardCharsets.UTF_8)));
            //7.关闭连接
            socketChannel.close();
        }
    }
}

NIO与BIO的比较:

1.BIO是以流的方式处理数据的,而NIO以缓冲区的方式处理数据,缓冲区IO效率比流IO的效率高很多
2.BIO是阻塞的,NIO则是非阻塞的
3.BIO一个线程处理一个连接请求,而NIO有选择器可以实现单线程监听多个客户端连接.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值