JavaNIO(2)、Linux网络I/O模型

一、阻塞I/O (Blocking I/O)

  1. 阻塞I/O模式下的一个读取操作流程

    在这里插入图片描述

    默认情况下的所有socket都是blocking的。

    应用程序发起recvfrom系统调用,这时候可能网络中还没有数据到达,就会阻塞

    等到网络中有完整的数据到达后,系统将从内核缓存区拷贝数据到应用程序缓存区。

    这种模式下整个处理线程都会被阻塞,影响程序效率。这是一个同步阻塞操作

    白话点就是,你找系统要数据,系统现在没有数据也不回复你任何信息,你只能一直在这里等着,直到拿到数据为止。

二、非阻塞I\O (Non-Blocking I/O)

可以设置socket的属性使其变为non-blocking。对一个非阻塞的socket执行读操作时的流程如下

在这里插入图片描述

socket为非阻塞的情况下,调用recvfrom()时不管数据是否准备好,会立即得到返回。

当数据未准备好时,会收到一个ewouldblock返回。这时在应用程序中只能定时的循环调用recvfrom,直到返回一个OK为止。

定时循环调用时会有两个问题

如果频率设置过高,会浪费CPU时间

如果频率设置过低,可能数据处理不及时。这是一个同步非阻塞操作

白话说就是,你找系统要数据,系统现在没有,并且告诉了你说现在没有。你就过一段时间来询问一次,过一段时间来询问一次,直到拿到数据为止。

三、I/O多路复用 (I/O Multiplexing)

上面说的阻塞和非阻塞都是讨论的一个socket连接的情况,如果是多个socket连接就需要使用多线程处理。

I/O多路复用可以使用一个线程处理多个socket连接的情况。看下面多个socket执行读操作的情况

在这里插入图片描述

应用程序调用select()系统方法,会被阻塞,系统会监控所有select负责的socket连接,直到其中一个socket连接有数据到达时,该调用才会返回。

然后应用程序再发起recvfrom()调用读取数据。

IO多路复用的优势在于能在一个线程中处理大量的socket连接,但是当连接数量很小时,使用多线程+阻塞IO的方式的效率可能更高。

在IO多路复用模型中,每一个socket一般都设置为非阻塞的。但是select的调用会阻塞工作线程。

白话描述就是,现在有很多人想从系统处获得数据,但是不是所有人都来调用系统函数,而是专门有一个代理人说:“你们都在这里等着吧,有数据来了我叫你们”。这时代理人也等待系统的回复。当有数据到达时,代理人找到对应的人,叫他去读取数据,其他人继续等待,如此反复。这是一个同步阻塞操作

在linux下IO多路复用有下面几种模式:

  • select

    select的特点是,它仅仅知道了有数据准备完成,但是不知道是那个连接对应的数据(可能是一个,多个,全部)。所以只能轮询select负责的所有连接,找出有事件完成的连接。时间复杂度O(n)。

    select还有一个最大连接数的限制。

  • poll

    poll和select本质上是一样的,都是轮询所有的连接。但是它没有最大连接数限制,因为它是基于链表来存储的。时间复杂度O(n)。

  • epoll

    epoll会使用通知的方式告诉应用程序是哪个连接的I/O事件准备好了,通过对应的连接处理I/O事件即可,不需要轮询。时间复杂度O(1)。

四、信号驱动I/O (Signal Driven I/O)

信号驱动IO模式下的socket读取流程如下

在这里插入图片描述

首先,应用程序向系统注册一个信号处理函数

然后应用程序继续执行

当socket有数据时,系统通过生成一个信号的方式通知该应用程序数据已准备好

应用程序再调用recvfrom获取数据。这是一个同步非阻塞操作

白话表述就是,你给系统留了一个通信方式,当数据准备好后,系统通知你去读,你再从系统处读取数据。

五、异步I/O (AIO)

异步IO模型下的socket读取数据时的流程如下

在这里插入图片描述

异步IO只需要发起一次系统调用,当数据准备完成时,也不需要应用程序再发起系统调用来读取数据,系统会自己把数据拷贝到应用程序缓存区中,并通知应该程序数据已经拷贝完成。

这个模型是真正意义上的异步IO,异步非阻塞操作

白话表述就是,你想从系统处获取数据,但是现在数据还没有准备好,然后你告诉系统当数据准备好时,把数据复制到xxx地方,并且通知你一声。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值