几种服务器端IO模型的简单介绍及实现(转载)

作者:阿凡卢

出处:http://www.cnblogs.com/luxiaoxun/

服务器端几种模型:

1、阻塞式模型(blocking IO)

我们第一次接触到的网络编程都是从 listen()、accpet()、send()、recv() 等接口开始的。使用这些接口可以很方便的构建C/S的模型。这里大部分的 socket 接口都是阻塞型的。所谓阻塞型接口是指系统调用(一般是 IO 接口)不返回调用结果并让当前线程一直阻塞,只有当该系统调用获得结果或者超时出错时才返回。

如下面一个简单的Server端实现:

 View Code

示意图如下:

这里的socket的接口是阻塞的(blocking),在线程被阻塞期间,线程将无法执行任何运算或响应任何的网络请求,这给多客户机、多业务逻辑的网络编程带来了挑战。

2、多线程的服务器模型(Multi-Thread)

应对多客户机的网络应用,最简单的解决方式是在服务器端使用多线程(或多进程)。多线程(或多进程)的目的是让每个连接都拥有独立的线程(或进程),这样任何一个连接的阻塞都不会影响其他的连接。

多线程Server端的实现:

 View Code

上述多线程的服务器模型可以解决一些连接量不大的多客户端连接请求,但是如果要同时响应成千上万路的连接请求,则无论多线程还是多进程都会严重占据系统资源,降低系统对外界响应效率。

在多线程的基础上,可以考虑使用“线程池”或“连接池”,“线程池”旨在减少创建和销毁线程的频率,其维持一定合理数量的线程,并让空闲的线程重新承担新的执行任务。“连接池”维持连接的缓存池,尽量重用已有的连接、减少创建和关闭连接的频率。这两种技术都可以很好的降低系统开销,都被广泛应用很多大型系统。

3、非阻塞式模型(Non-blocking IO)

非阻塞的接口相比于阻塞型接口的显著差异在于,在被调用之后立即返回。

非阻塞型IO的示意图如下:

从应用程序的角度来说,blocking read 调用会延续很长时间。在内核执行读操作和其他工作时,应用程序会被阻塞。

非阻塞的IO可能并不会立即满足,需要应用程序调用许多次来等待操作完成。这可能效率不高,因为在很多情况下,当内核执行这个命令时,应用程序必须要进行忙碌等待,直到数据可用为止。

另一个问题,在循环调用非阻塞IO的时候,将大幅度占用CPU,所以一般使用select等来检测”是否可以操作“。

4、多路复用IO

支持I/O复用的系统调用有select、poll、epoll、kqueue等,

这里以Select函数为例,select函数用于探测多个文件句柄的状态变化,以下为一个使用了使用了Select函数的Server实现:

 View Code

示意图如下:

这里Select监听的socket都是Non-blocking的,所以在do_read() do_write()中对返回为EAGAIN/WSAEWOULDBLOCK都做了处理。

从代码中可以看出使用Select返回后,仍然需要轮训再检测每个socket的状态(读、写),这样的轮训检测在大量连接下也是效率不高的。因为当需要探测的句柄值较大时,select () 接口本身需要消耗大量时间去轮询各个句柄。

很多操作系统提供了更为高效的接口,如 linux 提供 了 epoll,BSD 提供了 kqueue,Solaris 提供了 /dev/poll …。如果需要实现更高效的服务器程序,类似 epoll 这样的接口更被推荐。遗憾的是不同的操作系统特供的 epoll 接口有很大差异,所以使用类似于 epoll 的接口实现具有较好跨平台能力的服务器会比较困难。

5、使用事件驱动库libevent的服务器模型

Libevent 是一种高性能事件循环/事件驱动库。

为了实际处理每个请求,libevent 库提供一种事件机制,它作为底层网络后端的包装器。事件系统让为连接添加处理函数变得非常简便,同时降低了底层IO复杂性。这是 libevent 系统的核心。

创建 libevent 服务器的基本方法是,注册当发生某一操作(比如接受来自客户端的连接)时应该执行的函数,然后调用主事件循环 event_dispatch()。执行过程的控制现在由 libevent 系统处理。注册事件和将调用的函数之后,事件系统开始自治;在应用程序运行时,可以在事件队列中添加(注册)或 删除(取消注册)事件。事件注册非常方便,可以通过它添加新事件以处理新打开的连接,从而构建灵活的网络处理系统。

使用Libevent实现的一个回显服务器如下:

 View Code

6、信号驱动IO模型(Signal-driven IO)

使用信号,让内核在描述符就绪时发送SIGIO信号通知应用程序,称这种模型为信号驱动式I/O(signal-driven I/O)。

图示如下:

首先开启套接字的信号驱动式I/O功能,并通过sigaction系统调用安装一个信号处理函数。该系统调用将立即返回,我们的进程继续工作,也就是说进程没有被阻塞。当数据报准备好读取时,内核就为该进程产生一个SIGIO信号。随后就可以在信号处理函数中调用recvfrom读取数据报,并通知主循环数据已经准备好待处理,也可以立即通知主循环,让它读取数据报。

无论如何处理SIGIO信号,这种模型的优势在于等待数据报到达期间进程不被阻塞。主循环可以继续执行 ,只要等到来自信号处理函数的通知:既可以是数据已准备好被处理,也可以是数据报已准备好被读取。

7、异步IO模型(asynchronous IO)

异步I/O(asynchronous I/O)由POSIX规范定义。演变成当前POSIX规范的各种早起标准所定义的实时函数中存在的差异已经取得一致。一般地说,这些函数的工作机制是:告知内核启动某个操作,并让内核在整个操作(包括将数据从内核复制到我们自己的缓冲区)完成后通知我们。这种模型与前一节介绍的信号驱动模型的主要区别在于:信号驱动式I/O是由内核通知我们何时可以启动一个I/O操作,而异步I/O模型是由内核通知我们I/O操作何时完成。

示意图如下:

我们调用aio_read函数(POSIX异步I/O函数以aio_或lio_开头),给内核传递描述符、缓冲区指针、缓冲区大小(与read相同的三个参数)和文件偏移(与lseek类似),并告诉内核当整个操作完成时如何通知我们。该系统调用立即返回,并且在等待I/O完成期间,我们的进程不被阻塞。本例子中我们假设要求内核在操作完成时产生某个信号,该信号直到数据已复制到应用进程缓冲区才产生,这一点不同于信号驱动I/O模型。

 

参考:

《UNIX网络编程》

使用 libevent 和 libev 提高网络应用性能:http://www.ibm.com/developerworks/cn/aix/library/au-libev/

使用异步 I/O 大大提高应用程序的性能:https://www.ibm.com/developerworks/cn/linux/l-async/

 

作者:阿凡卢
出处:http://www.cnblogs.com/luxiaoxun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载于:https://www.cnblogs.com/lizhanwu/articles/4169734.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/257869.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

html细边框表格代码,html中表格细边框的四种实现及其比较.doc

html中表格细边框的四种实现及其比较?html中表格细边框的四种实现及其比较第一种使用css!--- 华丽的分隔线。。 -- .box ?border-top-width: 1px;?border-right-width: 0px;?border-bottom-width: 0px;?border-left-width: 1px;?border-top-style: solid;?border-right-…

margin 等高布局

<div id"main"><div id"left">我是左边的内容的啦啦啦啦。。。。<br> 我是左边的内容的啦啦啦啦。。。。<br> 我是左边的内容的啦啦啦啦。。。。<br> 我是左边的内容的啦啦啦啦。。。。<br> 我是左边的内容的啦啦啦啦…

c、c++---linux上的GetTickCount函数

http://blog.csdn.net/guang11cheng/article/details/6865992 http://wenda.so.com/q/1378766306062794

C#判断一个类中有无指定名称的方法

C#中可以通过反射分析元数据来解决这个问题&#xff0c;示例代码如下&#xff1a;12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849using System;using System.Reflection;namespace Hello{class Program{static void Main(string[…

2021年高考成绩查询襄阳状元,大胆猜测一下,2021年高考,湖北省文理状元会花落谁家?...

随着2021年高考的逼近&#xff0c;考生进入紧张有序的复习中&#xff0c;家长也在为孩子筹谋着哪所学校更适合&#xff0c;作为吃瓜群众的我们&#xff0c;可能更关注今年湖北省的文理科状元会花落谁家&#xff0c;要知道&#xff0c;一所学校如果可以出现一名高考状元&#xf…

为什么写Java程序需要接口

为什么写Java程序需要接口 我之所以以这个作为标题&#xff0c;并不是为了玩噱头&#xff0c;讲一些似是而非的空话&#xff0c;还是以探索加发现&#xff0c; 追本溯源的讲解一下为什么Java需要接口&#xff0c;怎么理解&#xff0c;怎么用它。 首先接口并不是Java才有的&…

《领域特定语言》一1.5使用代码生成

1.5使用代码生成 在迄今为止的讨论中&#xff0c;要处理DSL&#xff0c;组装“语义模型”&#xff08;第11章&#xff09;&#xff0c;然后执行语义模型&#xff0c;提供我们希望从控制器得到的行为。在语言圈子里&#xff0c;这种方式称为解释&#xff08;interpretation&…

SVG 基础图形

SVG 基础图形 SVG包含了以下的基础图形元素&#xff1a; 矩形&#xff08;包括可选的圆角&#xff09;&#xff0c;使用<rect>元素创建圆形&#xff0c;使用<circle>元素创建椭圆形&#xff0c;使用<ellipse>元素创建直线&#xff0c;使用<line>元素创…

枣庄三中高考2021成绩查询,2021枣庄中考成绩查询系统入口

2021枣庄中考成绩查询系统入口2021-05-20 19:11:35文/王佳慧2021年&#xff0c;枣庄的中考时间快到了&#xff0c;本文分享了枣庄中考成绩查询入口&#xff0c;系统开通后考生可登陆查询成绩。枣庄中考成绩查询入口志愿填报须知1.录取标准&#xff1a;提前批、第一批、第三批学…

移动端”宴席知多少

转载(http://adt.aicai.com/index.php/archives/179/) 瞎折腾移动端的项目已经很长一段时间了&#xff0c;并不像其它企业一样&#xff0c;可以有项目组去完成&#xff0c;基本都是一个人瞎尝试&#xff0c;时而web&#xff0c;时而web app。恍恍惚惚过了这段岁月&#xff0c;也…

快速的取整方法(~~)

为什么80%的码农都做不了架构师&#xff1f;>>> 最近看一篇js装逼小技巧————双波浪号的妙用(将内容转化为数字,或者小数取整)&#xff0c;但是本身我的JavaScript水平比较低对其底层操作和其使用范围不甚了解&#xff1b;通过翻阅资料现进行简单的整理。 ###装…

git log友好显示

查看commit 提交日志 $ git log $git log --prettyoneline $git reflog 显示所有提交记录&#xff0c;包括已经回退的提交&#xff0c;如图&#xff1a;提交了abc 和 bb 然后回退到 abc   $git log 只显示abc提交 可以使用 $git reset --hard commit号 回退到bb git reflog…

jprofiler_windows-x64_9_1注册码

L-Larry_Lau163.com#5481-ucjn4a16rvd98#6038 L-Larry_Lau163.com#36573-fdkscp15axjj6#25257 转载于:https://www.cnblogs.com/sprinng/p/5104507.html

南理工计算机技术专业学位,南京理工大学计算机技术(专业学位)考研难吗

很多考生在准备南京理工大学计算机技术(专业学位)考研难吗&#xff1f;是考研报考的时候都会产生这样的疑问&#xff1a;这个专业的研究生好吗&#xff1f;适合我吗&#xff1f;对我以后的人生和职业会有帮助吗&#xff1f;考生在准备南京理工大学计算机技术(专业学位)专业考研…

《分布式系统:概念与设计》一2.3.2 体系结构模式

2.3.2 体系结构模式 体系结构模式构建在上述讨论过的相对原始的体系结构元素之上&#xff0c;提供组合的、重复出现的结构&#xff0c;这些结构在给定的环境中能运行良好。它们未必是完整的解决方案&#xff0c;但当与其他模式组合时&#xff0c;它们会更好地引导设计者给出一…

javascript sort()实现元素json对象的排序

看以下代码&#xff1a; var s [ { name: "Robin Van PurseStrings", age: 30 } ,{ name: "Theo Walcott", age: 24 } ,{ name: "Bacary Sagna", age: 28 } ].sort(function(obj1, obj2) {// 实现增序排列&#xff1a;前者的 age 小于后者…

html5手机签名,html5手写签名

var canvas, board;canvas document.getElementById(myCanvas);canvas.height 300;canvas.width 400;board canvas.getContext(2d);board.lineWidth 1; //设置画笔粗细board.strokeStyle "#f00";board.lineJoin "round"; //设置画笔轨迹基于圆点拼接…

调查:Java程序员最伤心,C++程序员最年老

说起我们对编程世界现有的刻板印象&#xff0c;你一定听说过类似于没有人喜欢用Java编码或者使用C 都是老人家&#xff0c;等等这样的话。为了分析这些刻板印象背后的真相&#xff0c;Trestle Technology的数据工程师写了一个工具。 不知道你有没有听说过微软的Project Oxford&…

mysql一些写常用命令

参见pcttcnc2007博客腾飞 1.mysql的status信息命令: mysql> show global status; 2.可以列出mysql服务器运行各种状态值&#xff0c;另外&#xff0c;查询mysql服务器配置信息语句&#xff1a; mysql> show variables; 3.连接数 经 常会遇见”mysql: error 1040: too man…

计算机不小心删除怎么找回桌面,如何将桌面上误删的文件找回

在如今工作电脑化的趋势下&#xff0c;用户都会在桌面上创建各种各样的文件等&#xff0c;这些文件都是需要在工作中经常要进行各种操作的重要文件&#xff0c;那么频繁的操作也会出现各种的意外情况等&#xff0c;如果不小心删除了重要的文件该怎么恢复呢&#xff1f;想要恢复…