JavaIO四大模型:BIO(同步阻塞IO)

IO读写原理

        用户进程进行的IO读写,都会用到read和write两大系统调用。

        read系统调用:将数据从内核缓冲区复制到进程缓冲区中。

        write系统调用:将数据从进程缓冲区复制到内核缓冲区。

        在操作系统需要访问系统资源时,需要借助于内核态,系统资源主要有:CPU、输入输出、进程管理、内存、进程间通信。这些系统资源,在用户线程中是无法被直接访问的,只有通过操作系统来访问。所以把操作系统访问这些资源的功能,称为系统调用。

        缓冲区:目的是为了减少频繁的系统IO调用。

        系统调用需要从用户态切换到内核态,切换之后保存用户进程的数据和状态等信息。

        结束调用之后需要恢复之前的信息,为了消除这种损耗的时间,还有损耗性能的时间,就有了缓冲区。有了缓冲区,操作系统使用read函数从内核缓冲区赋值到进程缓冲区,write函数从进程缓冲区复制到内核缓冲区,只有缓冲区中的数据达到一定量时,再进行IO系统调用。

        阻塞与非阻塞:阻塞和非阻塞用来描述用户线程调用内核IO操作的方式。

        阻塞是指IO操作需要彻底完成后,才返回到用户空间。

        非阻塞指IO操作被调用后,立即给用户一个状态,无需等到IO操作彻底完成。

Java I/O底层流程

在这里插入图片描述

四大模型之:BIO同步阻塞IO

        客户端每发一次请求,服务端都会创建一个新的线程来处理这个请求。即使这个请求什么都不干,服务器依然会创建一个新的线程来处理。
在这里插入图片描述

        同步阻塞IO,客户端使用Sokcet,服务端使用:ServerSocket。

        客户端使用Socket指定一个IP地址和端口号,此时操作系统会为Socket实例分配一个未使用的端口号,并创建一个包含本地和远程地址、端口号的数据结构,这个数据结构会一直保存,直到连接结束。在真正完成Socket实例创建之前,会进行3次握手,握手成功后,才算真正的创建了Socket实例。

        服务端使用ServerSocket指定一个端口号,操作系统也会为ServerSocket实例创建一个包含端口号和监听的地址的通配符的数据结构,之后,会调用accept(),用来监听这个端口上的连接请求。这个方法是阻塞的,只有一个新连接请求来时,才会继续往下执行。新连接请求来时,会创建一个新的Socket数据结构,这个数据结构里包含着源地址和要请求的端口号信息。这个新的Socket会关联到ServerSocket一个未完成的连接数据结构中,此时ServerSocket还不算创建成功,直至三次握手后,才算创建成功。ServerSocket所关联的列表中每一个数据结构,都代表一个TCP连接。

        BIO示意图:
在这里插入图片描述
        即,在用户发起IO系统调用时,用户线程会进入阻塞状态。在等待内核缓冲区的数据复制到用户缓冲区这个过程是阻塞的,直到IO调用完毕,用户线程才会不阻塞。

        BIO的一对一实现(一个服务器对应一个客户端请求)

//BIOServer:
public class BIOServer {
   
    public static void main(String[] args) {
   
        ServerSocket serverSocket = null;
        BufferedReader bufferedReader = null;
        BufferedOutputStream bos = null;
        try {
   
            serverSocket = new ServerSocket(3333);
            System.out.println("服务端已启动...");
            // 监听3333端口上的连接请求,该方法是一个阻塞方法,
            // 如果没有请求,则会一直阻塞,直到有请求。
            Socket accept = serverSocket.accept();
            //执行到这,说明有请求
            System.out.println("连接建立成功");

            while(true){
   
                //服务器先读取客户端的消息:
                // 调用accept.getInputStream,获取连接的字节流。
                // 再将字节流转换为字符流,在添加一层缓冲流。加快读取
                bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
                
                // 获取流中的信息
                String s = bufferedReader.readLine();
                if ("exit".equals
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值