Java中IO模型之BIO(同步阻塞模型)

Java中IO模型之BIO(同步阻塞模型)

BIO:同步阻塞模型

在JDK1.4之前,建立网络通信采用的BIO模型
需要现在服务器启动一个ServerSocket,然后客户端启动一个Socket来对服务端进行连接,默认的情况下服务端需要对每一个请求建立一个线程等待处理,客户端发送请求后,需要等待服务端是否有相应的线程来处理客户端的连接,如果没有线程则会一致等待或者拒绝请求,如果有的话,客户端会等待线程来处理客户端请求

在了解BIO模型之前先让我们回顾一下Socket通信流程
Java中IO模型之BIO(同步阻塞模型)_第1张图片

基于BIO的编程

通过网络通信模拟echo命令的实现

服务端编程:

ServerSocket ssocket = null;
        try {
            //创建ServerSocket实例
            ssocket = new ServerSocket();
            //绑定端口
            ssocket.bind(new InetSocketAddress(9999));
            System.out.println("服务端已经启动...");

            //进行监听,等待客户端的连接
            Socket socket = ssocket.accept();
            System.out.println("客户端:"+socket.getRemoteSocketAddress()+"连接上");

            //进行读写操作
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String msg = reader.readLine();
            System.out.println("客户端:"+socket.getRemoteSocketAddress()+"发送消息:"+msg);
            //回复客户端消息
            OutputStream write = socket.getOutputStream();
            write.write(("echo:"+msg+"\n").getBytes());

            //关闭资源
            write.close();
            reader.close();
            socket.close();
            System.out.println("服务端结束");

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ssocket != null) {
                try {
                    ssocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

客户端编程:

//启动socket实例
        Socket socket = new Socket();

        try {
            //连接服务端
            socket.connect(new InetSocketAddress("127.0.0.1",9999));
            System.out.println("客户端连接服务端成功");

            //进行读写操作
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write("hello\n".getBytes());
            outputStream.flush();

            //读数据
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String msg = reader.readLine();
            System.out.println(msg);

            //关闭资源
            reader.close();
            outputStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

BIO的编程流程

服务端:
1、创建ServerSocket实例
2、绑定端口
3、通过accept来监听客户端的连接,有客户端连接会返回socket实例
4、进行读写操作
5、关闭资源

客户端:
1、创建socket实例
2、通过connect并指定服务端的IP+端口连接服务端
3、进行读写操作
4、关闭资源

BIO是同步阻塞模型,BIO编程中阻塞体现在哪里?

accept方法:阻塞接收客户端的连接

read方法/write方法

connect方法:和服务端建立连接,连接的过程中connect会阻塞

服务端可以处理很多的客户端的连接?

怎么设计考虑呢??
在accept能进行循环接收客户端连接,借助于多线程处理
主线程负责接收客户端的连接:accept放在主线程执行
子线程负责和客户端交互,每一个客户端连接都分配一个子线程

Java中IO模型之BIO(同步阻塞模型)_第2张图片

多线程+BIO完成多用户请求处理

服务端编程:

public class MutilThreadBIOServer {
    public static void main(String[] args) {
        try {
            //创建serverSocket实例
            ServerSocket serverSocket = new ServerSocket();

            //绑定端口
            serverSocket.bind(new InetSocketAddress(9999));
            System.out.println("服务端启动了");

            while (true) {
                //等待多个客户端的连接
                Socket socket = serverSocket.accept();
                System.out.println("客户端:"+socket.getRemoteSocketAddress()+" 上线了");

                //将Socket实例交给子线程处理
                new ServerHandler(socket).start();
            }

            //关闭资源
//            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class ServerHandler extends Thread{
    private Socket socket;

    /**
     * 构造函数,将socket实例传递给子线程
     * @param socket
     */
    public ServerHandler(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            //读取客户端的消息
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //回复消息
            OutputStream outputStream = socket.getOutputStream();
            String msg = null;
            while ((msg = reader.readLine())!= null) {
                System.out.println("客户端:"+socket.getRemoteSocketAddress()+" 消息:"+msg);

                //给客户端回复消息
                outputStream.write((msg+"\n").getBytes());

                //循环结束条件
                if ("".equals(msg) || "exit".equals(msg)) break;
            }

            //关闭资源
            reader.close();
            outputStream.close();
            System.out.println("客户端:"+socket.getRemoteSocketAddress()+" 关闭");
            socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

通过分析BIO,在多个用户的连接情况下,为了达到服务端处理的并发量,就需要对每一个用户的连接要分配一个新线程来处理
但是线程资源时有限的,不能无限制的创建出新的资源,那么对于高并发的支持也就大打折扣了。所以随即在jdk1.4之后提出来NIO的模型!

你可能感兴趣的:(Java中IO模型之BIO(同步阻塞模型))