IO

基础

I/O输入/输出(Input/Output),提供对文件读写操作

按流向分:

输入流:程序可以从中读取数据的流。

输出流:程序能向其中写入数据的流。

按数据传输单位分:

字节流:以字节为单位传输数据的流

字符流:以字符为单位传输数据的流

 

InputStream       字节输入流超类

OutputStream    字节输出流超类

Read                   字符输入流超类

Writer                 字符输出流超类

BIO(同步阻塞)

通过下面的测试很容易就能看出来在serverSocket.accept()和in.read(by)时发生线程阻塞情况,这段时间线程占用系统资源却没有工作,给系统造成不必要的资源开销。即使采用多线程in.read(by)也会在子线程中发生阻塞,线程数量过多时系统负担太大,并且数据读取缓慢

public class Server {
    public static void main(String[] args) throws Exception{
        ServerSocket serverSocket = new ServerSocket(8181);
        System.out.println("等待客户端连接");
        Socket socket = serverSocket.accept();
        InputStream in = socket.getInputStream();
        byte[] by = new byte[1024];
        System.out.println("等待客户端传输数据");
        in.read(by);
        System.out.println(new String(by));
        OutputStream out = socket.getOutputStream();
        Thread.sleep(5000);
        out.write("测试反馈".getBytes());
    }
}
public class Client {
    public static void main(String[] args) throws Exception{
        Socket socket = new Socket("127.0.0.1", 8181);
        OutputStream out = socket.getOutputStream();
        Thread.sleep(5000);
        out.write("这是一个测试".getBytes());
        InputStream in = socket.getInputStream();
        byte[] by = new byte[1024];
        System.out.println("等待服务端传输数据");
        in.read(by);
        System.out.println("客户端接收数据:" + new String(by));
    }
}

NIO(同步非阻塞)

NIO中要提供了Selector、Channel和Buffer三个核心组件

Selector:可以绑定多个Channel通道并监听通道事件,Channel通道事件有连接、接收、读和写事件

Channel:是NIO传输数据的通道,可以向通道读数据和写数据

Buffer:NIO基于Channel通道和Buffer缓存区进行数据传输,在通道中读写数据使用的就是Buffer缓存区

NIO主要是通过遍历所有注册在Selector选择器上并发生事件的Channel通道,根据判断发生事件类型进行不同操作

public class Server {
    public static void main(String[] args) throws Exception{

        /* 配置服务器Socket通道 */
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        /* 设置非阻塞模式 */
        serverSocketChannel.configureBlocking(false);
        /* 绑定端口 */
        serverSocketChannel.socket().bind(new InetSocketAddress(1212));

        /* 配置选择器 */
        Selector selector = Selector.open();
        /* 设置指定通道的监听模式 */
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true){
            /* 判断是否存在准备好IO操作的通道 */
            if(selector.select() == 0){
                continue;
            }
            System.out.println("触发事件");
            /* 遍历所有准备好的通道 */
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()){
                SelectionKey selectionKey = iterator.next();
                /* 获取后的通道要清除,否则会重复遍历 */
                iterator.remove();

                /* 客户端准备连接,开始配置 */
                if(selectionKey.isAcceptable()){
                    ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel();
                    /* 获取客户端通道 */
                    SocketChannel socketChannel = server.accept();
                    socketChannel.configureBlocking(false);
                    /* 设置客户端通道监听模式 */
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }
                /* 准备读取客户端发送过来的数据 */
                else if(selectionKey.isReadable()){
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    try {
                        /* 输出数据发送给客户端 */
                        socketChannel.write(ByteBuffer.wrap("服务器返回数据".getBytes()));
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        int x = socketChannel.read(byteBuffer);
                        if(x > 0){
                            System.out.println(new String(byteBuffer.array()));
                        }
                        else {
                            socketChannel.close();
                        }
                    }
                    catch (Exception e){
                        try {
                            socketChannel.close();
                        }
                        catch (Exception e1){

                        }
                    }
                }
            }
        }
    }
}
public class Client {
    public static void main(String[] args) throws  Exception{
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        socketChannel.connect(new InetSocketAddress("127.0.0.1", 1212));
        Selector selector = Selector.open();
        socketChannel.register(selector, SelectionKey.OP_CONNECT);
        while (true){
            if(selector.select() == 0){
                continue;
            }
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()){
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                /* 判断与服务器连接是否完成 */
                if(selectionKey.isConnectable()){
                    SocketChannel server = (SocketChannel) selectionKey.channel();
                    /* 判断Socket通道连接是否完成,配置监听模式 */
                    if(server.finishConnect()){
                        socketChannel.register(selectionKey.selector(), SelectionKey.OP_READ);
                        socketChannel.write(ByteBuffer.wrap("客户端返回数据".getBytes()));
                    }
                }
                else if(selectionKey.isReadable()){
                    SocketChannel socket = (SocketChannel) selectionKey.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    socket.read(byteBuffer);
                    System.out.println(new String(byteBuffer.array()));
                }
            }
        }
    }
}

AIO(异步非阻塞)

等IO操作完成之后才会通知线程,由系统自动触发,AIO操作基于事件和回调机制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值