《Unix网络编程:卷1》中介绍了5中I/O模型,JAVA作为运行在宿主机上的程序,底层也遵循这5中I/O模型规则。这5中I/O模型分别是:

  • 阻塞式IO
  • 非阻塞式IO
  • I/O复用
  • 信号驱动式IO
  • 异步IO

按POSIX标准来分,IO分为同步和异步,上面的前4钟都属于同步IO,具体后面解释。

在介绍IO模型之前,需要先了解应用程序IO的过程,一般来说,一个IO分为两个阶段

应用程序向操作系统发出IO请求:应用程序发出IO请求给操作系统内核,操作系统内核需要等待数据就绪,这里的数据可能来自别的应用程序或者网络

  1. 等待数据:数据可能来自其他应用程序或者网络,如果没有数据,操作系统就一直等待,应用程序就跟着等待。
  2. 拷贝数据:将就绪的数据拷贝到应用程序工作区。

在Unix系统中,操作系统的IO操作是一个系统调用recvfrom(),即一个系统调用recvfrom包含两步,等待数据就绪和拷贝数据。

阻塞式IO模型

正如上面的IO操作的步骤,当应用程序发起IO请求之后,操作系统就要处理系统调用recvfrom(),在这个过程中,操作系统需要等待数据就绪(数据可能来自别的应用程序的输入或者网络),应用程序则不再处理别的事情,而是一直等待(即阻塞状态)数据就绪,然后操作系统完成IO操作,然后recvfrom()才方法返回,应用程序才继续执行,这就是阻塞式IO模型。下图描述了阻塞式IO模型

非阻塞式IO模型

当应用程序发起了IO请求之后,系统调用recvfrom()被执行,并且立即返回,但是返回的并不是IO处理完成的结果,而是一个特定的错误,表示IO数据没有准备好,因此不需要进行IO操作。应用程序会不停地(即轮询)执行recvfrom()系统调用,直到数据已经就绪,然后操作系统完成IO操作,recvfrom()返回成功。这个过程中,没有数据就绪时系统调用recvfrom()是立即返回的,即应用程序并没有阻塞在底层操作系统的等待数据上面,而是轮询结果。这个过程可以用下图表示,

可见阻塞IO与非阻塞IO的关键区别在于,系统调用recvfrom是否立即返回。由于轮询会消耗大量CPU时间,因此这种模式并不常用。

IO复用模型(多路复用)

前面的非阻塞IO将会轮询一个IO是否可用,而IO复用则是轮询多个IO是否至少有一个可用。

IO复用的关键在于select()函数。在阻塞IO中,应用程序阻塞在一个IO的内核操作上;

但在多路复用中,通过select(),可以同时监听多个IO请求的内核操作,只要有任意一个IO的内核操作就绪,都可以通知select()返回,再进行系统调用recvfrom()完成IO操作。

这个过程应用程序就可以同时监听多个IO请求,这比起基于多线程阻塞式IO要先进得多,因为服务器只需要一两个线程就可以进行多客户端通信。IO复用可用下图表示,

信号驱动式IO模型

在unix系统中,应用程序发起IO请求时,可以给IO请求注册一个信号函数,请求立即返回,操作系统底层则处于等待状态(等待数据就绪),直到数据就绪,然后通过信号通知主调程序,主调程序才去调用系统函数recvfrom()完成IO操作。

信号驱动也是一种非阻塞式的IO模型,比起上面的非阻塞式IO模型,信号驱动式IO模型不需要轮询检查底层IO数据是否就绪,而是被动接收信号,然后再调用recvfrom执行IO操作。

比起多路复用IO模型来说,信号驱动IO模型针对的是一个IO的完成过程, 而多路复用IO模型针对的是多个IO同时进行时候的场景。 信号驱动式IO模型用下图表示,

异步IO模型

异步IO模型的工作机制是,将整个IO操作(包括等待数据就绪,复制数据到应用程序工作空间)全都交给操作系统完成,操作系统完成整个过程之后,再通知应用程序。

异步IO模型跟信号驱动IO模型很相似,但是区别是信号驱动模型是在数据就绪的时候通知应用程序,应用程序再调用系统函数recvfrom进行IO操作。

而异步IO模型则是数据就绪且操作系统已经将数据拷贝进应用程序运行空间之后,操作系统再通知应用程序,这个过程中应用程序不需要阻塞。异步IO可以如下图表示,

IO模型对比

可见前面四种IO模型中,应用程序都会在某一环节阻塞(即使是轮询,也算是一种阻塞),POSIX将这种IO模型称为同步IO操作,

而异步IO模型,则是全权把IO操作整个过程都交给操作系统,中途无阻塞,POSIX将这种IO模型称为异步IO操作。  以上所有IO对比如下图,

JAVA基础知识之网络编程——-网络通信模型(IO模型)的更多相关文章

  1. JAVA基础知识之面向对象编程知识汇总

    JAVA基础课程部分面向对象已经学习完成,知识结构如下: 总体知识框架: 类的结构: 面向对象编程三大特征: 关键字和抽象类接口等: 常见知识汇总: 成员变量和局部变量比较 有无返回值方法比较: 权限 ...

  2. JAVA基础知识总结17(网络编程)

    端口: 物理端口:IP地址 逻辑端口:用于标识进程的逻辑地址,不同进程的标识:有效端口:0~65535,其中0~1024系统使用或保留端口. JAVA中ip对象:InetAddress. import ...

  3. JAVA基础知识之JDBC——编程步骤及执行SQL

    JDBC编程步骤 下面以mysql数据库为例, 1.加载驱动 首先需要下载数据库的驱动jar文件,并且在eclipse包中加入到class path中去, 例如mysql的驱动文件 mysql-con ...

  4. JAVA基础知识之网络编程——-网络基础(Java的http get和post请求,多线程下载)

    本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web ...

  5. Java基础复习笔记系列 九 网络编程

    Java基础复习笔记系列之 网络编程 学习资料参考: 1.http://www.icoolxue.com/ 2. 1.网络编程的基础概念. TCP/IP协议:Socket编程:IP地址. 中国和美国之 ...

  6. [转] - Linux网络编程 -- 网络知识介绍

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  7. java基础知识精华

    转载:https://www.jianshu.com/p/6c078abb720f java基础知识 java内存模型 java运行时数据区域 hashMap 如何解决冲突 存储方式 冲突达到一定数量 ...

  8. 学习Spring必学的Java基础知识(1)----反射(转)

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...

  9. 学习Spring必学的Java基础知识(1)----反射

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...

  10. Java基础知识总结(超级经典)

    Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java ...

随机推荐

  1. 测试常用SQL注入语句大全

    转载自Cracer,标题:<渗透常用SQL注入语句大全>,链接http://www.xxxx.com/?p=2226 1.判断有无注入点 整形参数判断 1.直接加' 2.and 1=1 3 ...

  2. Spring的quartz定时器同一时刻重复执行二次的问题解决

    最近用Spring的quartz定时器的时候,发现到时间后,任务总是重复执行两次,在tomcat或jboss下都如此. 打印出他们的hashcode,发现是不一样的,也就是说,在web容器启动的时候, ...

  3. Codeforces Round #192 (Div. 2)

    吐槽一下,这次的CF好简单啊. 可是我为什么这么粗心这么大意这么弱.把心沉下来,想想你到底想做什么! A 题意:O(-1) 思路:O(-1) #include <iostream> #in ...

  4. HTML - 毛玻璃 滤镜 模糊

    css 秘密花园 http://dabblet.com/gist/d9f243ddd7dbffa341a4 场景,背景图片 + 毛玻璃遮盖 原理:利用background的cover特性,将毛玻璃的区 ...

  5. ready是先执行的,load后执行,DOM文档的加载步骤

    在jq中在文档载入完毕后有这几种方式去执行指定函数: $(document).ready(function() { // ...代码... }); //document ready 简写 $(func ...

  6. Codeforces Round #346 (Div. 2) E F

    因为很久没有个人认真做题了 昨天晚上开了场虚拟cf来锻炼个人手速 选的是第一次做cf的场 那时候7出3还被hack...之后也没补题 这次做的时候顺便回忆了一下以前比赛的时候是怎么想的 发现经验还是很 ...

  7. UIWebView如何获取内容高度

    iOS UIWebView如何获取到内容的高度呢?我们经常会遇到项目中需要使用UIWebView来加载H5页面,但是页面的高度并不确定,而我们前端需要根据内容的高度呈现出来,且不允许webview滚动 ...

  8. JS,分页

    <!DOCTYPE html><html lang="en"><head> <meta charset="utf-8" ...

  9. 深入浅出Docker(一):Docker核心技术预览

    Docker是PaaS供应商dotCloud开源的一个基于LXC 的高级容器引擎,源代码托管在 GitHub 上, 基于Go语言开发并遵从Apache 2.0协议开源.Docker提供了一种在安全.可 ...

  10. 带AI的俄罗斯方块源码

    好久没写俄罗斯方块的游戏了.从学习编程到现在,相继用Win32 API.MFC.C.C#.JS.iOS写过大约二十款左右的俄罗斯方块游戏.最近用Cocos2d-x写了一下,第一次完全将游戏逻辑与UI层 ...