五种IO模型

目录

 

一、同步阻塞(BIO)

二、同步非阻塞

三、I/O复用(NIO)

1.selector

2.channel

四、信号I/O

五、异步非阻塞(AIO)


一、同步阻塞(BIO)

发送方发送请求之后一直等待响应。 接收方处理请求时进行的IO操作如果不能马上等到返回结果,就一直等到返回结果后,才响应发送方,期间不能进行其他工作。

代码:

sever端

public class BIOClient {
    private Socket socket;
    private Scanner scanner;
    private final int port = 5676;
    private final String IP = "127.0.0.1";
    private BufferedWriter writer;
    private BufferedReader reader;
    private OutputStream outputStream;
    private InputStream inputStream;
    private volatile boolean flag = true;

    public BIOClient() {
        scanner = new Scanner(System.in);
        try {
            socket = new Socket(IP, port);  //请求和服务器建立连接
            //TCP三次握手的起点  只要这个socket 建立成功说明连接建立成功
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void startClient() {
        try {
            boolean closed = socket.isClosed();
            if (!closed) {
                outputStream = socket.getOutputStream();//负责发送消息
                inputStream = socket.getInputStream();// 负责接收消息
                writer = new BufferedWriter(new OutputStreamWriter(outputStream));
                reader = new BufferedReader(new InputStreamReader(inputStream));
                new Thread(new SendThread()).start();
                while (flag) {
                    String str = reader.readLine();
                    System.out.println("接受到服务器的信息为 : " + str);

                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
                inputStream.close();
                outputStream.close();
                reader.close();
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    class SendThread implements Runnable {

        @Override
        public void run() {
            while (true) {
                System.out.println("请输入回复信息:");
                String s = scanner.nextLine();
                try {
                    writer.write(s + "\n");
                    writer.flush();
                    if (s.equals("exit")) {
                        flag = false;
                        break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

client端


//TCP协议代码
public class BIOServer {
    private ServerSocket socket;//开发TCP的工具包
    private final int port = 5676;


    public BIOServer() {
        try {
            //将服务器绑定到特定端口上
            socket = new ServerSocket(port);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void startTCPServer() {
        //接收客户端的请求
        try {
            while (true) {  //不停的接收客户端请求
                Socket clientSocket = socket.accept();  //阻塞方法   阻塞到连接建立上为止
                //TCP 建立连接  三次握手   三次握手的终点
//            clientSocket请求连接的用户一一对应
                //后面讲使用该clientSocket进行和这个用户之间的通信
                new Thread(new ServerHandler(clientSocket)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

二、同步非阻塞

 

发送方发送请求之后,一直等待响应。 接受方处理请求时进行的IO操作如果不能马上的得到结果,就立即返回,取做其他事情。 但是由于没有得到请求处理结果,不响应发送方,发送方一直等待。 当IO操作完成以后,将完成状态和结果通知接收方,接收方再响应发送方,发送方才进入下一次请求过程。(实际不应用)

三、I/O复用(NIO)

I0多路复用的好处就在于单个进程就可以同时处理多个网络连接的I0。它的基本原理就是不再由应用程序自己监视连接,取而代之由内核替应用程序监视文件描述符。

1.selector

Selector称为选择器,当然你也可以翻译为多路复用器。它是Java NIO核心组件中的-个,用于检查-个或多个NIO Channel (通道)的状态是否处于可读、可写。Selector 提供选择已经就绪的任务的能力: Selector 会不断检测注册在其上的Channel,如果某个Channel.上面发生读或者写事件,这个Channel就处于就绪状态,会被Selector轮询出来,然后通做出相对应的操作。

2.channel

channel用户I0操作的连接,由java.nio.channels包定义,原有I0的一-种补充,但是不能直接访问数据需要和缓冲区Buffer进行交互。与Selector - -起使用时,Channel 必须处于非阻塞模式下。

NIO服务器端:

public class NIOServer {
    private int port = 5676;
    private ServerSocketChannel serverChannel;
    private FileChannel fileChannel;
    //    private Selector selector;
    private ByteBuffer recBuffer;
    private ByteBuffer sendBuffer;

    public NIOServer() {
        try {
            serverChannel = ServerSocketChannel.open();
            serverChannel.bind(new InetSocketAddress(port));
            recBuffer = ByteBuffer.allocate(1024);
            sendBuffer = ByteBuffer.allocate(1024);
            fileChannel = FileChannel.open(Paths.get(
                    "D:\\tmp\\one\\two\\three\\channel.txt"),
                    StandardOpenOption.WRITE, StandardOpenOption.CREATE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void startNIOServer() throws IOException {
        SocketChannel socketChannel = serverChannel.accept();
        while (socketChannel.read(recBuffer) != -1) {//read一直阻塞等待客户端传输数据
            recBuffer.flip();
            fileChannel.write(recBuffer);
            recBuffer.clear();
        }
        //接受客户端的数据
        //给客户端回复信息
        sendBuffer.put("服务器已经接收到文件".getBytes());
        sendBuffer.flip();
        socketChannel.write(sendBuffer);
        socketChannel.close();
        fileChannel.close();
        serverChannel.close();

    }
}

handler

public class ServerHandler implements Runnable {
    private Socket clientSocket;
    private BufferedWriter writer;
    private BufferedReader reader;
    private OutputStream outputStream;
    private InputStream inputStream;
    private Scanner scanner;

    public ServerHandler(Socket clientSocket) {
        scanner = new Scanner(System.in);
        this.clientSocket = clientSocket;
        try {
            outputStream = clientSocket.getOutputStream();//负责发送消息
            inputStream = clientSocket.getInputStream();// 负责接收消息
            //字节转字符的过程
            //文件传输
//            BufferedOutputStream outputStream1 = new BufferedOutputStream(outputStream);
            writer = new BufferedWriter(new OutputStreamWriter(outputStream));
            reader = new BufferedReader(new InputStreamReader(inputStream));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            while (true) {
                String str = reader.readLine();
                System.out.println("接受到客户端的信息为 : " + str);
                if (str.equals("exit")) {
                    break;
                }
                System.out.println("请输入回复信息:");
                String s = scanner.nextLine();
                writer.write(s + "\n");
                writer.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
                outputStream.close();
                reader.close();
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

客户端:

public class NIOClient {
    private int port = 5676;
    private SocketChannel socketChannel;
    private FileChannel fileChannel;
    //    private Selector selector;
    private ByteBuffer recBuffer;
    private ByteBuffer sendBuffer;

    public NIOClient() {
        try {
            socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", port));
            recBuffer = ByteBuffer.allocate(1024);
            sendBuffer = ByteBuffer.allocate(1024);
            fileChannel = FileChannel.open(Paths.get(
                    "D:\\tmp\\one\\two\\three\\Newchannel.txt"),
                    StandardOpenOption.READ, StandardOpenOption.CREATE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void startClient() throws IOException {
        while (fileChannel.read(sendBuffer) != -1) {
            sendBuffer.flip();
            socketChannel.write(sendBuffer);
            sendBuffer.clear();

        }
        //等待接收服务器的回值
        int len = -1;
        while ((len = socketChannel.read(recBuffer)) != -1) {
            System.out.println(new String(recBuffer.array(), 0, len));
            recBuffer.clear();
        }
    }

四、信号I/O

允许Socket进行信号驱动I0,并注册一-个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到- -个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。

五、异步非阻塞(AIO)

 

发送方发送请求之后,一直等待响应。 接受方处理请求时进行的IO操作如果不能马上的得到结果,就立即返回,取做其他事情。 但是由于没有得到请求处理结果,不响应发送方,发送方一直等待。 当IO操作完成以后,将完成状态和结果通知接收方,接收方再响应发送方,发送方才进入下一次请求过程。(实际不应用)

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值